diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index 16e3d6c00..80a485122 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -1,651 +1,651 @@ -// Copyright (c) 2012-2016 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 #include #include #include #include #include #include class CAddrManTest : public CAddrMan { public: explicit CAddrManTest(bool makeDeterministic = true) { if (makeDeterministic) { // Set addrman addr placement to be deterministic. MakeDeterministic(); } } //! Ensure that bucket placement is always the same for testing purposes. void MakeDeterministic() { nKey.SetNull(); insecure_rand = FastRandomContext(true); } 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; // Set last good connection in the deep past. Good_(addr, true, nLastSuccess); bool count_failure = false; int64_t nLastTry = GetAdjustedTime() - 61; Attempt(addr, count_failure, nLastTry); } }; static CNetAddr ResolveIP(const char *ip) { CNetAddr addr; BOOST_CHECK_MESSAGE(LookupHost(ip, addr, false), strprintf("failed to resolve: %s", ip)); return addr; } static CNetAddr ResolveIP(std::string ip) { return ResolveIP(ip.c_str()); } static CService ResolveService(const char *ip, int port = 0) { CService serv; BOOST_CHECK_MESSAGE(Lookup(ip, serv, port, false), strprintf("failed to resolve: %s:%i", ip, port)); return serv; } static CService ResolveService(std::string ip, int port = 0) { return ResolveService(ip.c_str(), port); } BOOST_FIXTURE_TEST_SUITE(addrman_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(addrman_simple) { CAddrManTest addrman; CNetAddr source = ResolveIP("252.2.2.2"); // Test: Does Addrman respond correctly when empty. BOOST_CHECK_EQUAL(addrman.size(), 0U); CAddrInfo addr_null = addrman.Select(); BOOST_CHECK_EQUAL(addr_null.ToString(), "[::]:0"); // Test: Does Addrman::Add work as expected. CService addr1 = ResolveService("250.1.1.1", 8333); BOOST_CHECK(addrman.Add(CAddress(addr1, NODE_NONE), source)); BOOST_CHECK_EQUAL(addrman.size(), 1U); CAddrInfo addr_ret1 = addrman.Select(); BOOST_CHECK_EQUAL(addr_ret1.ToString(), "250.1.1.1:8333"); // Test: Does IP address deduplication work correctly. // Expected dup IP should not be added. CService addr1_dup = ResolveService("250.1.1.1", 8333); BOOST_CHECK(!addrman.Add(CAddress(addr1_dup, NODE_NONE), source)); BOOST_CHECK_EQUAL(addrman.size(), 1U); // Test: New table has one addr and we add a diff addr we should // have at least one addr. // Note that addrman's size cannot be tested reliably after insertion, as // hash collisions may occur. But we can always be sure of at least one // success. CService addr2 = ResolveService("250.1.1.2", 8333); BOOST_CHECK(addrman.Add(CAddress(addr2, NODE_NONE), source)); BOOST_CHECK(addrman.size() >= 1); // Test: AddrMan::Clear() should empty the new table. addrman.Clear(); BOOST_CHECK_EQUAL(addrman.size(), 0U); CAddrInfo addr_null2 = addrman.Select(); BOOST_CHECK_EQUAL(addr_null2.ToString(), "[::]:0"); // Test: AddrMan::Add multiple addresses works as expected std::vector vAddr; vAddr.push_back(CAddress(ResolveService("250.1.1.3", 8333), NODE_NONE)); vAddr.push_back(CAddress(ResolveService("250.1.1.4", 8333), NODE_NONE)); BOOST_CHECK(addrman.Add(vAddr, source)); BOOST_CHECK(addrman.size() >= 1); } BOOST_AUTO_TEST_CASE(addrman_ports) { CAddrManTest addrman; CNetAddr source = ResolveIP("252.2.2.2"); BOOST_CHECK_EQUAL(addrman.size(), 0U); // Test: 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_EQUAL(addrman.size(), 1U); CService addr1_port = ResolveService("250.1.1.1", 8334); 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"); // Test: Add same IP but diff port to tried table, it doesn't get added. // Perhaps this is not ideal behavior but it is the current behavior. addrman.Good(CAddress(addr1_port, NODE_NONE)); BOOST_CHECK_EQUAL(addrman.size(), 1U); bool newOnly = true; CAddrInfo addr_ret3 = addrman.Select(newOnly); BOOST_CHECK_EQUAL(addr_ret3.ToString(), "250.1.1.1:8333"); } BOOST_AUTO_TEST_CASE(addrman_select) { CAddrManTest addrman; CNetAddr source = ResolveIP("252.2.2.2"); // 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_EQUAL(addrman.size(), 1U); bool newOnly = true; CAddrInfo addr_ret1 = addrman.Select(newOnly); BOOST_CHECK_EQUAL(addr_ret1.ToString(), "250.1.1.1:8333"); // Test: move addr to tried, select from new expected nothing returned. addrman.Good(CAddress(addr1, NODE_NONE)); BOOST_CHECK_EQUAL(addrman.size(), 1U); CAddrInfo addr_ret2 = addrman.Select(newOnly); BOOST_CHECK_EQUAL(addr_ret2.ToString(), "[::]:0"); CAddrInfo addr_ret3 = addrman.Select(); BOOST_CHECK_EQUAL(addr_ret3.ToString(), "250.1.1.1:8333"); BOOST_CHECK_EQUAL(addrman.size(), 1U); // Add three addresses to new table. CService addr2 = ResolveService("250.3.1.1", 8333); 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)); // 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)); addrman.Good(CAddress(addr5, NODE_NONE)); 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)); addrman.Good(CAddress(addr7, NODE_NONE)); // Test: 6 addrs + 1 addr from last test = 7. BOOST_CHECK_EQUAL(addrman.size(), 7U); // Test: Select pulls from new and tried regardless of port number. std::set ports; for (int i = 0; i < 20; ++i) { ports.insert(addrman.Select().GetPort()); } BOOST_CHECK_EQUAL(ports.size(), 3U); } BOOST_AUTO_TEST_CASE(addrman_new_collisions) { CAddrManTest addrman; CNetAddr source = ResolveIP("252.2.2.2"); BOOST_CHECK_EQUAL(addrman.size(), 0U); 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); // Test: No collision in new table yet. BOOST_CHECK_EQUAL(addrman.size(), i); } // Test: new table collision! CService addr1 = ResolveService("250.1.1.18"); 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_EQUAL(addrman.size(), 18U); } BOOST_AUTO_TEST_CASE(addrman_tried_collisions) { CAddrManTest addrman; CNetAddr source = ResolveIP("252.2.2.2"); BOOST_CHECK_EQUAL(addrman.size(), 0U); 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); addrman.Good(CAddress(addr, NODE_NONE)); // Test: No collision in tried table yet. BOOST_CHECK_EQUAL(addrman.size(), i); } // Test: tried table collision! CService addr1 = ResolveService("250.1.1.80"); 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_EQUAL(addrman.size(), 80U); } BOOST_AUTO_TEST_CASE(addrman_find) { CAddrManTest addrman; BOOST_CHECK_EQUAL(addrman.size(), 0U); CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE); CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE); CAddress addr3 = CAddress(ResolveService("251.255.2.1", 8333), NODE_NONE); 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); // Test: ensure Find returns an IP matching what we searched on. CAddrInfo *info1 = addrman.Find(addr1); BOOST_REQUIRE(info1); BOOST_CHECK_EQUAL(info1->ToString(), "250.1.2.1:8333"); // Test: Find does not discriminate by port number. CAddrInfo *info2 = addrman.Find(addr2); BOOST_REQUIRE(info2); BOOST_CHECK_EQUAL(info2->ToString(), info1->ToString()); // Test: Find returns another IP matching what we searched on. CAddrInfo *info3 = addrman.Find(addr3); BOOST_REQUIRE(info3); BOOST_CHECK_EQUAL(info3->ToString(), "251.255.2.1:8333"); } BOOST_AUTO_TEST_CASE(addrman_create) { CAddrManTest addrman; BOOST_CHECK_EQUAL(addrman.size(), 0U); CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE); CNetAddr source1 = ResolveIP("250.1.2.1"); int nId; CAddrInfo *pinfo = addrman.Create(addr1, source1, &nId); // Test: The result should be the same as the input addr. BOOST_CHECK_EQUAL(pinfo->ToString(), "250.1.2.1:8333"); CAddrInfo *info2 = addrman.Find(addr1); BOOST_CHECK_EQUAL(info2->ToString(), "250.1.2.1:8333"); } BOOST_AUTO_TEST_CASE(addrman_delete) { CAddrManTest addrman; BOOST_CHECK_EQUAL(addrman.size(), 0U); CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE); CNetAddr source1 = ResolveIP("250.1.2.1"); int nId; addrman.Create(addr1, source1, &nId); // Test: Delete should actually delete the addr. BOOST_CHECK_EQUAL(addrman.size(), 1U); addrman.Delete(nId); BOOST_CHECK_EQUAL(addrman.size(), 0U); CAddrInfo *info2 = addrman.Find(addr1); BOOST_CHECK(info2 == nullptr); } BOOST_AUTO_TEST_CASE(addrman_getaddr) { CAddrManTest addrman; // Test: Sanity check, GetAddr should never return anything if addrman // is empty. BOOST_CHECK_EQUAL(addrman.size(), 0U); std::vector vAddr1 = addrman.GetAddr(); BOOST_CHECK_EQUAL(vAddr1.size(), 0U); CAddress addr1 = CAddress(ResolveService("250.250.2.1", 8333), NODE_NONE); addr1.nTime = GetAdjustedTime(); // Set time so isTerrible = false CAddress addr2 = CAddress(ResolveService("250.251.2.2", 9999), NODE_NONE); addr2.nTime = GetAdjustedTime(); CAddress addr3 = CAddress(ResolveService("251.252.2.3", 8333), NODE_NONE); addr3.nTime = GetAdjustedTime(); CAddress addr4 = CAddress(ResolveService("252.253.3.4", 8333), NODE_NONE); addr4.nTime = GetAdjustedTime(); CAddress addr5 = CAddress(ResolveService("252.254.4.5", 8333), NODE_NONE); addr5.nTime = GetAdjustedTime(); CNetAddr source1 = ResolveIP("250.1.2.1"); 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); // GetAddr returns 23% of addresses, 23% of 5 is 1 rounded down. BOOST_CHECK_EQUAL(addrman.GetAddr().size(), 1U); // Test: Ensure GetAddr works with new and tried addresses. addrman.Good(CAddress(addr1, NODE_NONE)); addrman.Good(CAddress(addr2, NODE_NONE)); BOOST_CHECK_EQUAL(addrman.GetAddr().size(), 1U); // Test: Ensure GetAddr still returns 23% when addrman has many addrs. for (unsigned int i = 1; i < (8 * 256); i++) { int octet1 = i % 256; int octet2 = i >> 8 % 256; std::string strAddr = std::to_string(octet1) + "." + std::to_string(octet2) + ".1.23"; CAddress addr = CAddress(ResolveService(strAddr), NODE_NONE); // Ensure that for all addrs in addrman, isTerrible == false. addr.nTime = GetAdjustedTime(); addrman.Add(addr, ResolveIP(strAddr)); if (i % 8 == 0) { addrman.Good(addr); } } std::vector vAddr = addrman.GetAddr(); size_t percent23 = (addrman.size() * 23) / 100; BOOST_CHECK_EQUAL(vAddr.size(), percent23); BOOST_CHECK_EQUAL(vAddr.size(), 461U); // (Addrman.size() < number of addresses added) due to address collisions. BOOST_CHECK_EQUAL(addrman.size(), 2006U); } BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket) { CAddrManTest addrman; CAddress addr1 = CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE); CAddress addr2 = CAddress(ResolveService("250.1.1.1", 9999), NODE_NONE); CNetAddr source1 = ResolveIP("250.1.1.1"); CAddrInfo info1 = CAddrInfo(addr1, source1); uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash(); uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash(); BOOST_CHECK_EQUAL(info1.GetTriedBucket(nKey1), 40); // Test: Make sure key actually randomizes bucket placement. A fail on // this test could be a security issue. BOOST_CHECK(info1.GetTriedBucket(nKey1) != info1.GetTriedBucket(nKey2)); // Test: Two addresses with same IP but different ports can map to // different buckets because they have different keys. CAddrInfo info2 = CAddrInfo(addr2, source1); BOOST_CHECK(info1.GetKey() != info2.GetKey()); BOOST_CHECK(info1.GetTriedBucket(nKey1) != info2.GetTriedBucket(nKey1)); std::set buckets; for (int i = 0; i < 255; i++) { CAddrInfo infoi = CAddrInfo( CAddress(ResolveService("250.1.1." + std::to_string(i)), NODE_NONE), ResolveIP("250.1.1." + std::to_string(i))); int bucket = infoi.GetTriedBucket(nKey1); buckets.insert(bucket); } // Test: IP addresses in the same group (\16 prefix for IPv4) should // never get more than 8 buckets BOOST_CHECK_EQUAL(buckets.size(), 8U); buckets.clear(); for (int j = 0; j < 255; j++) { CAddrInfo infoj = CAddrInfo( CAddress(ResolveService("250." + std::to_string(j) + ".1.1"), NODE_NONE), ResolveIP("250." + std::to_string(j) + ".1.1")); int bucket = infoj.GetTriedBucket(nKey1); buckets.insert(bucket); } // Test: IP addresses in the different groups should map to more than // 8 buckets. BOOST_CHECK_EQUAL(buckets.size(), 160U); } BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) { CAddrManTest addrman; CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE); CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE); CNetAddr source1 = ResolveIP("250.1.2.1"); CAddrInfo info1 = CAddrInfo(addr1, source1); uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash(); uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash(); // Test: Make sure the buckets are what we expect BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1), 786); BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, source1), 786); // Test: Make sure key actually randomizes bucket placement. A fail on // this test could be a security issue. BOOST_CHECK(info1.GetNewBucket(nKey1) != info1.GetNewBucket(nKey2)); // Test: Ports should not affect bucket placement in the addr CAddrInfo info2 = CAddrInfo(addr2, source1); BOOST_CHECK(info1.GetKey() != info2.GetKey()); BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1), info2.GetNewBucket(nKey1)); std::set buckets; for (int i = 0; i < 255; i++) { CAddrInfo infoi = CAddrInfo( CAddress(ResolveService("250.1.1." + std::to_string(i)), NODE_NONE), ResolveIP("250.1.1." + std::to_string(i))); int bucket = infoi.GetNewBucket(nKey1); buckets.insert(bucket); } // Test: IP addresses in the same group (\16 prefix for IPv4) should // always map to the same bucket. BOOST_CHECK_EQUAL(buckets.size(), 1U); buckets.clear(); for (int j = 0; j < 4 * 255; j++) { CAddrInfo infoj = CAddrInfo( CAddress(ResolveService(std::to_string(250 + (j / 255)) + "." + std::to_string(j % 256) + ".1.1"), NODE_NONE), ResolveIP("251.4.1.1")); int bucket = infoj.GetNewBucket(nKey1); buckets.insert(bucket); } // Test: IP addresses in the same source groups should map to no more // than 64 buckets. BOOST_CHECK(buckets.size() <= 64); buckets.clear(); for (int p = 0; p < 255; p++) { CAddrInfo infoj = CAddrInfo(CAddress(ResolveService("250.1.1.1"), NODE_NONE), ResolveIP("250." + std::to_string(p) + ".1.1")); int bucket = infoj.GetNewBucket(nKey1); buckets.insert(bucket); } // Test: IP addresses in the different source groups should map to more // than 64 buckets. BOOST_CHECK(buckets.size() > 64); } BOOST_AUTO_TEST_CASE(addrman_selecttriedcollision) { CAddrManTest addrman; BOOST_CHECK(addrman.size() == 0); // Empty addrman should return blank addrman info. BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0"); // Add twenty two addresses. 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); addrman.Good(addr); // No collisions yet. BOOST_CHECK(addrman.size() == i); BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0"); } // Ensure Good handles duplicates well. for (unsigned int i = 1; i < 23; i++) { CService addr = ResolveService("250.1.1." + std::to_string(i)); addrman.Good(addr); BOOST_CHECK(addrman.size() == 22); BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0"); } } BOOST_AUTO_TEST_CASE(addrman_noevict) { CAddrManTest addrman; // Add twenty two addresses. 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); addrman.Good(addr); // No collision yet. BOOST_CHECK(addrman.size() == i); BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0"); } // Collision between 23 and 19. CService addr23 = ResolveService("250.1.1.23"); addrman.Add(CAddress(addr23, NODE_NONE), source); addrman.Good(addr23); BOOST_CHECK(addrman.size() == 23); BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "250.1.1.19:0"); // 23 should be discarded and 19 not evicted. addrman.ResolveCollisions(); BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0"); // 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); addrman.Good(addr); BOOST_CHECK(addrman.size() == i); BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0"); } // Cause a collision. CService addr33 = ResolveService("250.1.1.33"); 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); addrman.Good(addr23); BOOST_CHECK(addrman.size() == 33); BOOST_CHECK(addrman.SelectTriedCollision().ToString() != "[::]:0"); addrman.ResolveCollisions(); BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0"); } BOOST_AUTO_TEST_CASE(addrman_evictionworks) { CAddrManTest addrman; BOOST_CHECK(addrman.size() == 0); // Empty addrman should return blank addrman info. BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0"); // Add twenty two addresses. 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); addrman.Good(addr); // No collision yet. BOOST_CHECK(addrman.size() == i); BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0"); } // Collision between 23 and 19. CService addr = ResolveService("250.1.1.23"); addrman.Add(CAddress(addr, NODE_NONE), source); addrman.Good(addr); BOOST_CHECK(addrman.size() == 23); CAddrInfo info = addrman.SelectTriedCollision(); BOOST_CHECK(info.ToString() == "250.1.1.19:0"); // Ensure test of address fails, so that it is evicted. addrman.SimConnFail(info); // Should swap 23 for 19. addrman.ResolveCollisions(); 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); 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); addrman.Good(addr19); BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "250.1.1.23:0"); addrman.ResolveCollisions(); BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0"); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/allocator_tests.cpp b/src/test/allocator_tests.cpp index 65bd6f12f..8c5e8046a 100644 --- a/src/test/allocator_tests.cpp +++ b/src/test/allocator_tests.cpp @@ -1,244 +1,244 @@ -// Copyright (c) 2012-2016 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 #include #include #include #include BOOST_FIXTURE_TEST_SUITE(allocator_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(arena_tests) { // Fake memory base address for testing // without actually using memory. void *synth_base = reinterpret_cast(0x08000000); const size_t synth_size = 1024 * 1024; Arena b(synth_base, synth_size, 16); void *chunk = b.alloc(1000); #ifdef ARENA_DEBUG b.walk(); #endif BOOST_CHECK(chunk != nullptr); // Aligned to 16 BOOST_CHECK(b.stats().used == 1008); // Nothing has disappeared? BOOST_CHECK(b.stats().total == synth_size); b.free(chunk); #ifdef ARENA_DEBUG b.walk(); #endif BOOST_CHECK(b.stats().used == 0); BOOST_CHECK(b.stats().free == synth_size); try { // Test exception on double-free b.free(chunk); BOOST_CHECK(0); } catch (std::runtime_error &) { } void *a0 = b.alloc(128); void *a1 = b.alloc(256); void *a2 = b.alloc(512); BOOST_CHECK(b.stats().used == 896); BOOST_CHECK(b.stats().total == synth_size); #ifdef ARENA_DEBUG b.walk(); #endif b.free(a0); #ifdef ARENA_DEBUG b.walk(); #endif BOOST_CHECK(b.stats().used == 768); b.free(a1); BOOST_CHECK(b.stats().used == 512); void *a3 = b.alloc(128); #ifdef ARENA_DEBUG b.walk(); #endif BOOST_CHECK(b.stats().used == 640); b.free(a2); BOOST_CHECK(b.stats().used == 128); b.free(a3); BOOST_CHECK(b.stats().used == 0); BOOST_CHECK_EQUAL(b.stats().chunks_used, 0U); BOOST_CHECK(b.stats().total == synth_size); BOOST_CHECK(b.stats().free == synth_size); BOOST_CHECK_EQUAL(b.stats().chunks_free, 1U); std::vector addr; // allocating 0 always returns nullptr BOOST_CHECK(b.alloc(0) == nullptr); #ifdef ARENA_DEBUG b.walk(); #endif // Sweeping allocate all memory for (int x = 0; x < 1024; ++x) { addr.push_back(b.alloc(1024)); } BOOST_CHECK(b.stats().free == 0); // memory is full, this must return nullptr BOOST_CHECK(b.alloc(1024) == nullptr); BOOST_CHECK(b.alloc(0) == nullptr); for (int x = 0; x < 1024; ++x) { b.free(addr[x]); } addr.clear(); BOOST_CHECK(b.stats().total == synth_size); BOOST_CHECK(b.stats().free == synth_size); // Now in the other direction... for (int x = 0; x < 1024; ++x) { addr.push_back(b.alloc(1024)); } for (int x = 0; x < 1024; ++x) { b.free(addr[1023 - x]); } addr.clear(); // Now allocate in smaller unequal chunks, then deallocate haphazardly // Not all the chunks will succeed allocating, but freeing nullptr is // allowed so that is no problem. for (int x = 0; x < 2048; ++x) { addr.push_back(b.alloc(x + 1)); } for (int x = 0; x < 2048; ++x) { b.free(addr[((x * 23) % 2048) ^ 242]); } addr.clear(); // Go entirely wild: free and alloc interleaved, generate targets and sizes // using pseudo-randomness. for (int x = 0; x < 2048; ++x) { 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] = nullptr; } else if (!addr[idx]) { addr[idx] = b.alloc((s >> 16) & 2047); } bool lsb = s & 1; s >>= 1; // LFSR period 0xf7ffffe0 if (lsb) { s ^= 0xf00f00f0; } } for (void *ptr : addr) { b.free(ptr); } addr.clear(); BOOST_CHECK(b.stats().total == synth_size); BOOST_CHECK(b.stats().free == synth_size); } /** Mock LockedPageAllocator for testing */ class TestLockedPageAllocator : public LockedPageAllocator { public: TestLockedPageAllocator(int count_in, int lockedcount_in) : count(count_in), lockedcount(lockedcount_in) {} void *AllocateLocked(size_t len, bool *lockingSuccess) override { *lockingSuccess = false; if (count > 0) { --count; if (lockedcount > 0) { --lockedcount; *lockingSuccess = true; } // Fake address, do not actually use this memory return reinterpret_cast(0x08000000 + (count << 24)); } return nullptr; } void FreeLocked(void *addr, size_t len) override {} size_t GetLimit() override { return std::numeric_limits::max(); } private: int count; int lockedcount; }; BOOST_AUTO_TEST_CASE(lockedpool_tests_mock) { // Test over three virtual arenas, of which one will succeed being locked auto x = std::make_unique(3, 1); LockedPool pool(std::move(x)); BOOST_CHECK(pool.stats().total == 0); BOOST_CHECK(pool.stats().locked == 0); // Ensure unreasonable requests are refused without allocating anything void *invalid_toosmall = pool.alloc(0); BOOST_CHECK(invalid_toosmall == nullptr); BOOST_CHECK(pool.stats().used == 0); BOOST_CHECK(pool.stats().free == 0); void *invalid_toobig = pool.alloc(LockedPool::ARENA_SIZE + 1); BOOST_CHECK(invalid_toobig == nullptr); BOOST_CHECK(pool.stats().used == 0); BOOST_CHECK(pool.stats().free == 0); void *a0 = pool.alloc(LockedPool::ARENA_SIZE / 2); BOOST_CHECK(a0); BOOST_CHECK(pool.stats().locked == LockedPool::ARENA_SIZE); void *a1 = pool.alloc(LockedPool::ARENA_SIZE / 2); BOOST_CHECK(a1); void *a2 = pool.alloc(LockedPool::ARENA_SIZE / 2); BOOST_CHECK(a2); void *a3 = pool.alloc(LockedPool::ARENA_SIZE / 2); BOOST_CHECK(a3); void *a4 = pool.alloc(LockedPool::ARENA_SIZE / 2); BOOST_CHECK(a4); void *a5 = pool.alloc(LockedPool::ARENA_SIZE / 2); BOOST_CHECK(a5); // We've passed a count of three arenas, so this allocation should fail void *a6 = pool.alloc(16); BOOST_CHECK(!a6); pool.free(a0); pool.free(a2); pool.free(a4); pool.free(a1); pool.free(a3); pool.free(a5); BOOST_CHECK(pool.stats().total == 3 * LockedPool::ARENA_SIZE); BOOST_CHECK(pool.stats().locked == LockedPool::ARENA_SIZE); BOOST_CHECK(pool.stats().used == 0); } // These tests used the live LockedPoolManager object, this is also used by // other tests so the conditions are somewhat less controllable and thus the // tests are somewhat more error-prone. BOOST_AUTO_TEST_CASE(lockedpool_tests_live) { LockedPoolManager &pool = LockedPoolManager::Instance(); LockedPool::Stats initial = pool.stats(); void *a0 = pool.alloc(16); BOOST_CHECK(a0); // Test reading and writing the allocated memory *((uint32_t *)a0) = 0x1234; BOOST_CHECK(*((uint32_t *)a0) == 0x1234); pool.free(a0); try { // Test exception on double-free pool.free(a0); BOOST_CHECK(0); } catch (std::runtime_error &) { } // If more than one new arena was allocated for the above tests, something // is wrong BOOST_CHECK(pool.stats().total <= (initial.total + LockedPool::ARENA_SIZE)); // Usage must be back to where it started BOOST_CHECK(pool.stats().used == initial.used); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp index 86d2524ab..25ebac214 100644 --- a/src/test/amount_tests.cpp +++ b/src/test/amount_tests.cpp @@ -1,135 +1,135 @@ -// Copyright (c) 2016 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 #include #include #include BOOST_FIXTURE_TEST_SUITE(amount_tests, BasicTestingSetup) static void CheckAmounts(int64_t aval, int64_t bval) { Amount a(aval * SATOSHI), b(bval * SATOSHI); // Equality BOOST_CHECK_EQUAL(a == b, aval == bval); BOOST_CHECK_EQUAL(b == a, aval == bval); BOOST_CHECK_EQUAL(a != b, aval != bval); BOOST_CHECK_EQUAL(b != a, aval != bval); // Comparison BOOST_CHECK_EQUAL(a < b, aval < bval); BOOST_CHECK_EQUAL(b < a, bval < aval); BOOST_CHECK_EQUAL(a > b, aval > bval); BOOST_CHECK_EQUAL(b > a, bval > aval); BOOST_CHECK_EQUAL(a <= b, aval <= bval); BOOST_CHECK_EQUAL(b <= a, bval <= aval); BOOST_CHECK_EQUAL(a >= b, aval >= bval); BOOST_CHECK_EQUAL(b >= a, bval >= aval); // Unary minus BOOST_CHECK_EQUAL(-a, -aval * SATOSHI); BOOST_CHECK_EQUAL(-b, -bval * SATOSHI); // Addition and subtraction. BOOST_CHECK_EQUAL(a + b, b + a); BOOST_CHECK_EQUAL(a + b, (aval + bval) * SATOSHI); BOOST_CHECK_EQUAL(a - b, -(b - a)); BOOST_CHECK_EQUAL(a - b, (aval - bval) * SATOSHI); // Multiplication BOOST_CHECK_EQUAL(aval * b, bval * a); BOOST_CHECK_EQUAL(aval * b, (aval * bval) * SATOSHI); // Division if (b != Amount::zero()) { BOOST_CHECK_EQUAL(a / b, aval / bval); BOOST_CHECK_EQUAL(a / bval, (a / b) * SATOSHI); } if (a != Amount::zero()) { BOOST_CHECK_EQUAL(b / a, bval / aval); BOOST_CHECK_EQUAL(b / aval, (b / a) * SATOSHI); } // Modulus if (b != Amount::zero()) { BOOST_CHECK_EQUAL(a % b, a % bval); BOOST_CHECK_EQUAL(a % b, (aval % bval) * SATOSHI); } if (a != Amount::zero()) { BOOST_CHECK_EQUAL(b % a, b % aval); BOOST_CHECK_EQUAL(b % a, (bval % aval) * SATOSHI); } // OpAssign Amount v; BOOST_CHECK_EQUAL(v, Amount::zero()); v += a; BOOST_CHECK_EQUAL(v, a); v += b; BOOST_CHECK_EQUAL(v, a + b); v += b; BOOST_CHECK_EQUAL(v, a + 2 * b); v -= 2 * a; BOOST_CHECK_EQUAL(v, 2 * b - a); } BOOST_AUTO_TEST_CASE(AmountTests) { std::array values = {{-23, -1, 0, 1, 2, 3, 42, 99999999}}; for (int64_t i : values) { for (int64_t j : values) { CheckAmounts(i, j); } } BOOST_CHECK_EQUAL(COIN + COIN, 2 * COIN); BOOST_CHECK_EQUAL(2 * COIN + COIN, 3 * COIN); BOOST_CHECK_EQUAL(-1 * COIN + COIN, Amount::zero()); BOOST_CHECK_EQUAL(COIN - COIN, Amount::zero()); BOOST_CHECK_EQUAL(COIN - 2 * COIN, -1 * COIN); } BOOST_AUTO_TEST_CASE(MoneyRangeTest) { BOOST_CHECK_EQUAL(MoneyRange(-SATOSHI), false); BOOST_CHECK_EQUAL(MoneyRange(Amount::zero()), true); BOOST_CHECK_EQUAL(MoneyRange(SATOSHI), true); BOOST_CHECK_EQUAL(MoneyRange(MAX_MONEY), true); BOOST_CHECK_EQUAL(MoneyRange(MAX_MONEY + SATOSHI), false); } BOOST_AUTO_TEST_CASE(BinaryOperatorTest) { CFeeRate a, b; a = CFeeRate(1 * SATOSHI); b = CFeeRate(2 * SATOSHI); BOOST_CHECK(a < b); BOOST_CHECK(b > a); BOOST_CHECK(a == a); BOOST_CHECK(a <= b); BOOST_CHECK(a <= a); BOOST_CHECK(b >= a); BOOST_CHECK(b >= b); // a should be 0.00000002 BTC/kB now a += a; BOOST_CHECK(a == b); } BOOST_AUTO_TEST_CASE(ToStringTest) { CFeeRate feeRate; feeRate = CFeeRate(1 * SATOSHI); BOOST_CHECK_EQUAL(feeRate.ToString(), "0.00000001 BCH/kB"); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp index 72c8cb733..53db1e6ee 100644 --- a/src/test/arith_uint256_tests.cpp +++ b/src/test/arith_uint256_tests.cpp @@ -1,670 +1,670 @@ -// 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. #include #include #include #include #include #include #include #include #include #include #include BOOST_FIXTURE_TEST_SUITE(arith_uint256_tests, BasicTestingSetup) /// Convert vector to arith_uint256, via uint256 blob static inline arith_uint256 arith_uint256V(const std::vector &vch) { return UintToArith256(uint256(vch)); } const uint8_t R1Array[] = "\x9c\x52\x4a\xdb\xcf\x56\x11\x12\x2b\x29\x12\x5e\x5d\x35\xd2\xd2" "\x22\x81\xaa\xb5\x33\xf0\x08\x32\xd5\x56\xb1\xf9\xea\xe5\x1d\x7d"; const char R1ArrayHex[] = "7D1DE5EAF9B156D53208F033B5AA8122D2d2355d5e12292b121156cfdb4a529c"; // R1L equals roughly R1Ldouble * 2^256 const double R1Ldouble = 0.4887374590559308955; const arith_uint256 R1L = arith_uint256V(std::vector(R1Array, R1Array + 32)); const uint64_t R1LLow64 = 0x121156cfdb4a529cULL; const uint8_t R2Array[] = "\x70\x32\x1d\x7c\x47\xa5\x6b\x40\x26\x7e\x0a\xc3\xa6\x9c\xb6\xbf" "\x13\x30\x47\xa3\x19\x2d\xda\x71\x49\x13\x72\xf0\xb4\xca\x81\xd7"; const arith_uint256 R2L = arith_uint256V(std::vector(R2Array, R2Array + 32)); const char R1LplusR2L[] = "549FB09FEA236A1EA3E31D4D58F1B1369288D204211CA751527CFC175767850C"; const uint8_t ZeroArray[] = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; const arith_uint256 ZeroL = arith_uint256V(std::vector(ZeroArray, ZeroArray + 32)); const uint8_t OneArray[] = "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; const arith_uint256 OneL = arith_uint256V(std::vector(OneArray, OneArray + 32)); const uint8_t MaxArray[] = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"; const arith_uint256 MaxL = arith_uint256V(std::vector(MaxArray, MaxArray + 32)); const arith_uint256 HalfL = (OneL << 255); static std::string ArrayToString(const uint8_t A[], unsigned int width) { std::stringstream Stream; Stream << std::hex; for (unsigned int i = 0; i < width; ++i) { Stream << std::setw(2) << std::setfill('0') << (unsigned int)A[width - i - 1]; } return Stream.str(); } // constructors, equality, inequality BOOST_AUTO_TEST_CASE(basics) { BOOST_CHECK(1 == 0 + 1); // constructor arith_uint256(vector): BOOST_CHECK(R1L.ToString() == ArrayToString(R1Array, 32)); BOOST_CHECK(R2L.ToString() == ArrayToString(R2Array, 32)); BOOST_CHECK(ZeroL.ToString() == ArrayToString(ZeroArray, 32)); BOOST_CHECK(OneL.ToString() == ArrayToString(OneArray, 32)); BOOST_CHECK(MaxL.ToString() == ArrayToString(MaxArray, 32)); BOOST_CHECK(OneL.ToString() != ArrayToString(ZeroArray, 32)); // == and != BOOST_CHECK(R1L != R2L); BOOST_CHECK(ZeroL != OneL); BOOST_CHECK(OneL != ZeroL); BOOST_CHECK(MaxL != ZeroL); BOOST_CHECK(~MaxL == ZeroL); BOOST_CHECK(((R1L ^ R2L) ^ R1L) == R2L); uint64_t Tmp64 = 0xc4dab720d9c7acaaULL; for (unsigned int i = 0; i < 256; ++i) { BOOST_CHECK(ZeroL != (OneL << i)); BOOST_CHECK((OneL << i) != ZeroL); BOOST_CHECK(R1L != (R1L ^ (OneL << i))); BOOST_CHECK(((arith_uint256(Tmp64) ^ (OneL << i)) != Tmp64)); } BOOST_CHECK(ZeroL == (OneL << 256)); // String Constructor and Copy Constructor BOOST_CHECK(arith_uint256("0x" + R1L.ToString()) == R1L); BOOST_CHECK(arith_uint256("0x" + R2L.ToString()) == R2L); BOOST_CHECK(arith_uint256("0x" + ZeroL.ToString()) == ZeroL); BOOST_CHECK(arith_uint256("0x" + OneL.ToString()) == OneL); BOOST_CHECK(arith_uint256("0x" + MaxL.ToString()) == MaxL); BOOST_CHECK(arith_uint256(R1L.ToString()) == R1L); BOOST_CHECK(arith_uint256(" 0x" + R1L.ToString() + " ") == R1L); BOOST_CHECK(arith_uint256("") == ZeroL); BOOST_CHECK(R1L == arith_uint256(R1ArrayHex)); BOOST_CHECK(arith_uint256(R1L) == R1L); BOOST_CHECK((arith_uint256(R1L ^ R2L) ^ R2L) == R1L); BOOST_CHECK(arith_uint256(ZeroL) == ZeroL); BOOST_CHECK(arith_uint256(OneL) == OneL); // uint64_t constructor BOOST_CHECK((R1L & arith_uint256("0xffffffffffffffff")) == arith_uint256(R1LLow64)); BOOST_CHECK(ZeroL == arith_uint256(0)); BOOST_CHECK(OneL == arith_uint256(1)); BOOST_CHECK(arith_uint256("0xffffffffffffffff") == arith_uint256(0xffffffffffffffffULL)); // Assignment (from base_uint) arith_uint256 tmpL = ~ZeroL; BOOST_CHECK(tmpL == ~ZeroL); tmpL = ~OneL; BOOST_CHECK(tmpL == ~OneL); tmpL = ~R1L; BOOST_CHECK(tmpL == ~R1L); tmpL = ~R2L; BOOST_CHECK(tmpL == ~R2L); tmpL = ~MaxL; BOOST_CHECK(tmpL == ~MaxL); } static void shiftArrayRight(uint8_t *to, const uint8_t *from, unsigned int arrayLength, unsigned int bitsToShift) { for (unsigned int T = 0; T < arrayLength; ++T) { unsigned int F = (T + bitsToShift / 8); if (F < arrayLength) { to[T] = from[F] >> (bitsToShift % 8); } else { to[T] = 0; } if (F + 1 < arrayLength) { to[T] |= from[(F + 1)] << (8 - bitsToShift % 8); } } } static void shiftArrayLeft(uint8_t *to, const uint8_t *from, unsigned int arrayLength, unsigned int bitsToShift) { for (unsigned int T = 0; T < arrayLength; ++T) { if (T >= bitsToShift / 8) { unsigned int F = T - bitsToShift / 8; to[T] = from[F] << (bitsToShift % 8); if (T >= bitsToShift / 8 + 1) { to[T] |= from[F - 1] >> (8 - bitsToShift % 8); } } else { to[T] = 0; } } } // "<<" ">>" "<<=" ">>=" BOOST_AUTO_TEST_CASE(shifts) { uint8_t TmpArray[32]; arith_uint256 TmpL; for (unsigned int i = 0; i < 256; ++i) { shiftArrayLeft(TmpArray, OneArray, 32, i); BOOST_CHECK(arith_uint256V(std::vector( TmpArray, TmpArray + 32)) == (OneL << i)); TmpL = OneL; TmpL <<= i; BOOST_CHECK(TmpL == (OneL << i)); BOOST_CHECK((HalfL >> (255 - i)) == (OneL << i)); TmpL = HalfL; TmpL >>= (255 - i); BOOST_CHECK(TmpL == (OneL << i)); shiftArrayLeft(TmpArray, R1Array, 32, i); BOOST_CHECK(arith_uint256V(std::vector( TmpArray, TmpArray + 32)) == (R1L << i)); TmpL = R1L; TmpL <<= i; BOOST_CHECK(TmpL == (R1L << i)); shiftArrayRight(TmpArray, R1Array, 32, i); BOOST_CHECK(arith_uint256V(std::vector( TmpArray, TmpArray + 32)) == (R1L >> i)); TmpL = R1L; TmpL >>= i; BOOST_CHECK(TmpL == (R1L >> i)); shiftArrayLeft(TmpArray, MaxArray, 32, i); BOOST_CHECK(arith_uint256V(std::vector( TmpArray, TmpArray + 32)) == (MaxL << i)); TmpL = MaxL; TmpL <<= i; BOOST_CHECK(TmpL == (MaxL << i)); shiftArrayRight(TmpArray, MaxArray, 32, i); BOOST_CHECK(arith_uint256V(std::vector( TmpArray, TmpArray + 32)) == (MaxL >> i)); TmpL = MaxL; TmpL >>= i; BOOST_CHECK(TmpL == (MaxL >> i)); } arith_uint256 c1L = arith_uint256(0x0123456789abcdefULL); arith_uint256 c2L = c1L << 128; for (unsigned int i = 0; i < 128; ++i) { BOOST_CHECK((c1L << i) == (c2L >> (128 - i))); } for (unsigned int i = 128; i < 256; ++i) { BOOST_CHECK((c1L << i) == (c2L << (i - 128))); } } // ! ~ - BOOST_AUTO_TEST_CASE(unaryOperators) { BOOST_CHECK(~ZeroL == MaxL); uint8_t TmpArray[32]; for (unsigned int i = 0; i < 32; ++i) { TmpArray[i] = ~R1Array[i]; } BOOST_CHECK(arith_uint256V(std::vector(TmpArray, TmpArray + 32)) == (~R1L)); BOOST_CHECK(-ZeroL == ZeroL); BOOST_CHECK(-R1L == (~R1L) + 1); for (unsigned int i = 0; i < 256; ++i) { BOOST_CHECK(-(OneL << i) == (MaxL << i)); } } // Check if doing _A_ _OP_ _B_ results in the same as applying _OP_ onto each // element of Aarray and Barray, and then converting the result into an // arith_uint256. #define CHECKBITWISEOPERATOR(_A_, _B_, _OP_) \ for (unsigned int i = 0; i < 32; ++i) { \ TmpArray[i] = _A_##Array[i] _OP_ _B_##Array[i]; \ } \ BOOST_CHECK(arith_uint256V(std::vector( \ TmpArray, TmpArray + 32)) == (_A_##L _OP_ _B_##L)); #define CHECKASSIGNMENTOPERATOR(_A_, _B_, _OP_) \ TmpL = _A_##L; \ TmpL _OP_## = _B_##L; \ BOOST_CHECK(TmpL == (_A_##L _OP_ _B_##L)); BOOST_AUTO_TEST_CASE(bitwiseOperators) { uint8_t TmpArray[32]; CHECKBITWISEOPERATOR(R1, R2, |) CHECKBITWISEOPERATOR(R1, R2, ^) CHECKBITWISEOPERATOR(R1, R2, &) CHECKBITWISEOPERATOR(R1, Zero, |) CHECKBITWISEOPERATOR(R1, Zero, ^) CHECKBITWISEOPERATOR(R1, Zero, &) CHECKBITWISEOPERATOR(R1, Max, |) CHECKBITWISEOPERATOR(R1, Max, ^) CHECKBITWISEOPERATOR(R1, Max, &) CHECKBITWISEOPERATOR(Zero, R1, |) CHECKBITWISEOPERATOR(Zero, R1, ^) CHECKBITWISEOPERATOR(Zero, R1, &) CHECKBITWISEOPERATOR(Max, R1, |) CHECKBITWISEOPERATOR(Max, R1, ^) CHECKBITWISEOPERATOR(Max, R1, &) arith_uint256 TmpL; CHECKASSIGNMENTOPERATOR(R1, R2, |) CHECKASSIGNMENTOPERATOR(R1, R2, ^) CHECKASSIGNMENTOPERATOR(R1, R2, &) CHECKASSIGNMENTOPERATOR(R1, Zero, |) CHECKASSIGNMENTOPERATOR(R1, Zero, ^) CHECKASSIGNMENTOPERATOR(R1, Zero, &) CHECKASSIGNMENTOPERATOR(R1, Max, |) CHECKASSIGNMENTOPERATOR(R1, Max, ^) CHECKASSIGNMENTOPERATOR(R1, Max, &) CHECKASSIGNMENTOPERATOR(Zero, R1, |) CHECKASSIGNMENTOPERATOR(Zero, R1, ^) CHECKASSIGNMENTOPERATOR(Zero, R1, &) CHECKASSIGNMENTOPERATOR(Max, R1, |) CHECKASSIGNMENTOPERATOR(Max, R1, ^) CHECKASSIGNMENTOPERATOR(Max, R1, &) uint64_t Tmp64 = 0xe1db685c9a0b47a2ULL; TmpL = R1L; TmpL |= Tmp64; BOOST_CHECK(TmpL == (R1L | arith_uint256(Tmp64))); TmpL = R1L; TmpL |= 0; BOOST_CHECK(TmpL == R1L); TmpL ^= 0; BOOST_CHECK(TmpL == R1L); TmpL ^= Tmp64; BOOST_CHECK(TmpL == (R1L ^ arith_uint256(Tmp64))); } // <= >= < > BOOST_AUTO_TEST_CASE(comparison) { arith_uint256 TmpL; for (unsigned int i = 0; i < 256; ++i) { TmpL = OneL << i; BOOST_CHECK(TmpL >= ZeroL && TmpL > ZeroL && ZeroL < TmpL && ZeroL <= TmpL); BOOST_CHECK(TmpL >= 0 && TmpL > 0 && 0 < TmpL && 0 <= TmpL); TmpL |= R1L; BOOST_CHECK(TmpL >= R1L); BOOST_CHECK((TmpL == R1L) != (TmpL > R1L)); BOOST_CHECK((TmpL == R1L) || !(TmpL <= R1L)); BOOST_CHECK(R1L <= TmpL); BOOST_CHECK((R1L == TmpL) != (R1L < TmpL)); BOOST_CHECK((TmpL == R1L) || !(R1L >= TmpL)); BOOST_CHECK(!(TmpL < R1L)); BOOST_CHECK(!(R1L > TmpL)); } } BOOST_AUTO_TEST_CASE(plusMinus) { arith_uint256 TmpL = 0; BOOST_CHECK(R1L + R2L == arith_uint256(R1LplusR2L)); TmpL += R1L; BOOST_CHECK(TmpL == R1L); TmpL += R2L; BOOST_CHECK(TmpL == R1L + R2L); BOOST_CHECK(OneL + MaxL == ZeroL); BOOST_CHECK(MaxL + OneL == ZeroL); for (unsigned int i = 1; i < 256; ++i) { BOOST_CHECK((MaxL >> i) + OneL == (HalfL >> (i - 1))); BOOST_CHECK(OneL + (MaxL >> i) == (HalfL >> (i - 1))); TmpL = (MaxL >> i); TmpL += OneL; BOOST_CHECK(TmpL == (HalfL >> (i - 1))); TmpL = (MaxL >> i); TmpL += 1; BOOST_CHECK(TmpL == (HalfL >> (i - 1))); TmpL = (MaxL >> i); BOOST_CHECK(TmpL++ == (MaxL >> i)); BOOST_CHECK(TmpL == (HalfL >> (i - 1))); } BOOST_CHECK(arith_uint256(0xbedc77e27940a7ULL) + 0xee8d836fce66fbULL == arith_uint256(0xbedc77e27940a7ULL + 0xee8d836fce66fbULL)); TmpL = arith_uint256(0xbedc77e27940a7ULL); TmpL += 0xee8d836fce66fbULL; BOOST_CHECK(TmpL == arith_uint256(0xbedc77e27940a7ULL + 0xee8d836fce66fbULL)); TmpL -= 0xee8d836fce66fbULL; BOOST_CHECK(TmpL == 0xbedc77e27940a7ULL); TmpL = R1L; BOOST_CHECK(++TmpL == R1L + 1); BOOST_CHECK(R1L - (-R2L) == R1L + R2L); BOOST_CHECK(R1L - (-OneL) == R1L + OneL); BOOST_CHECK(R1L - OneL == R1L + (-OneL)); for (unsigned int i = 1; i < 256; ++i) { BOOST_CHECK((MaxL >> i) - (-OneL) == (HalfL >> (i - 1))); BOOST_CHECK((HalfL >> (i - 1)) - OneL == (MaxL >> i)); TmpL = (HalfL >> (i - 1)); BOOST_CHECK(TmpL-- == (HalfL >> (i - 1))); BOOST_CHECK(TmpL == (MaxL >> i)); TmpL = (HalfL >> (i - 1)); BOOST_CHECK(--TmpL == (MaxL >> i)); } TmpL = R1L; BOOST_CHECK(--TmpL == R1L - 1); } BOOST_AUTO_TEST_CASE(multiply) { BOOST_CHECK( (R1L * R1L).ToString() == "62a38c0486f01e45879d7910a7761bf30d5237e9873f9bff3642a732c4d84f10"); BOOST_CHECK( (R1L * R2L).ToString() == "de37805e9986996cfba76ff6ba51c008df851987d9dd323f0e5de07760529c40"); BOOST_CHECK((R1L * ZeroL) == ZeroL); BOOST_CHECK((R1L * OneL) == R1L); BOOST_CHECK((R1L * MaxL) == -R1L); BOOST_CHECK((R2L * R1L) == (R1L * R2L)); BOOST_CHECK( (R2L * R2L).ToString() == "ac8c010096767d3cae5005dec28bb2b45a1d85ab7996ccd3e102a650f74ff100"); BOOST_CHECK((R2L * ZeroL) == ZeroL); BOOST_CHECK((R2L * OneL) == R2L); BOOST_CHECK((R2L * MaxL) == -R2L); BOOST_CHECK(MaxL * MaxL == OneL); BOOST_CHECK((R1L * 0) == 0); BOOST_CHECK((R1L * 1) == R1L); BOOST_CHECK( (R1L * 3).ToString() == "7759b1c0ed14047f961ad09b20ff83687876a0181a367b813634046f91def7d4"); BOOST_CHECK( (R2L * 0x87654321UL).ToString() == "23f7816e30c4ae2017257b7a0fa64d60402f5234d46e746b61c960d09a26d070"); } BOOST_AUTO_TEST_CASE(divide) { arith_uint256 D1L("AD7133AC1977FA2B7"); arith_uint256 D2L("ECD751716"); BOOST_CHECK( (R1L / D1L).ToString() == "00000000000000000b8ac01106981635d9ed112290f8895545a7654dde28fb3a"); BOOST_CHECK( (R1L / D2L).ToString() == "000000000873ce8efec5b67150bad3aa8c5fcb70e947586153bf2cec7c37c57a"); BOOST_CHECK(R1L / OneL == R1L); BOOST_CHECK(R1L / MaxL == ZeroL); BOOST_CHECK(MaxL / R1L == 2); BOOST_CHECK_THROW(R1L / ZeroL, uint_error); BOOST_CHECK( (R2L / D1L).ToString() == "000000000000000013e1665895a1cc981de6d93670105a6b3ec3b73141b3a3c5"); BOOST_CHECK( (R2L / D2L).ToString() == "000000000e8f0abe753bb0afe2e9437ee85d280be60882cf0bd1aaf7fa3cc2c4"); BOOST_CHECK(R2L / OneL == R2L); BOOST_CHECK(R2L / MaxL == ZeroL); BOOST_CHECK(MaxL / R2L == 1); BOOST_CHECK_THROW(R2L / ZeroL, uint_error); } static bool almostEqual(double d1, double d2) { return fabs(d1 - d2) <= 4 * fabs(d1) * std::numeric_limits::epsilon(); } // GetHex SetHex size() GetLow64 GetSerializeSize, Serialize, Unserialize BOOST_AUTO_TEST_CASE(methods) { BOOST_CHECK(R1L.GetHex() == R1L.ToString()); BOOST_CHECK(R2L.GetHex() == R2L.ToString()); BOOST_CHECK(OneL.GetHex() == OneL.ToString()); BOOST_CHECK(MaxL.GetHex() == MaxL.ToString()); arith_uint256 TmpL(R1L); BOOST_CHECK(TmpL == R1L); TmpL.SetHex(R2L.ToString()); BOOST_CHECK(TmpL == R2L); TmpL.SetHex(ZeroL.ToString()); BOOST_CHECK(TmpL == 0); TmpL.SetHex(HalfL.ToString()); BOOST_CHECK(TmpL == HalfL); TmpL.SetHex(R1L.ToString()); BOOST_CHECK(R1L.size() == 32); BOOST_CHECK(R2L.size() == 32); BOOST_CHECK(ZeroL.size() == 32); BOOST_CHECK(MaxL.size() == 32); BOOST_CHECK(R1L.GetLow64() == R1LLow64); BOOST_CHECK(HalfL.GetLow64() == 0x0000000000000000ULL); BOOST_CHECK(OneL.GetLow64() == 0x0000000000000001ULL); for (unsigned int i = 0; i < 255; ++i) { BOOST_CHECK((OneL << i).getdouble() == ldexp(1.0, i)); } BOOST_CHECK(ZeroL.getdouble() == 0.0); for (int i = 256; i > 53; --i) { BOOST_CHECK( almostEqual((R1L >> (256 - i)).getdouble(), ldexp(R1Ldouble, i))); } uint64_t R1L64part = (R1L >> 192).GetLow64(); for (int i = 53; i > 0; --i) // doubles can store all integers in {0,...,2^54-1} exactly { BOOST_CHECK((R1L >> (256 - i)).getdouble() == (double)(R1L64part >> (64 - i))); } } BOOST_AUTO_TEST_CASE(bignum_SetCompact) { arith_uint256 num; bool fNegative; bool fOverflow; num.SetCompact(0, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x00123456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x01003456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x02000056, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x03000000, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x04000000, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x00923456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x01803456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x02800056, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x03800000, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x04800000, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x01123456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000012"); BOOST_CHECK_EQUAL(num.GetCompact(), 0x01120000U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); // Make sure that we don't generate compacts with the 0x00800000 bit set num = 0x80; BOOST_CHECK_EQUAL(num.GetCompact(), 0x02008000U); num.SetCompact(0x01fedcba, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "000000000000000000000000000000000000000000000000000000000000007e"); BOOST_CHECK_EQUAL(num.GetCompact(true), 0x01fe0000U); BOOST_CHECK_EQUAL(fNegative, true); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x02123456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000001234"); BOOST_CHECK_EQUAL(num.GetCompact(), 0x02123400U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x03123456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000000123456"); BOOST_CHECK_EQUAL(num.GetCompact(), 0x03123456U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x04123456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000012345600"); BOOST_CHECK_EQUAL(num.GetCompact(), 0x04123456U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x04923456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000012345600"); BOOST_CHECK_EQUAL(num.GetCompact(true), 0x04923456U); BOOST_CHECK_EQUAL(fNegative, true); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x05009234, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "0000000000000000000000000000000000000000000000000000000092340000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0x05009234U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0x20123456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL( num.GetHex(), "1234560000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK_EQUAL(num.GetCompact(), 0x20123456U); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, false); num.SetCompact(0xff123456, &fNegative, &fOverflow); BOOST_CHECK_EQUAL(fNegative, false); BOOST_CHECK_EQUAL(fOverflow, true); } // some more tests just to get 100% coverage BOOST_AUTO_TEST_CASE(getmaxcoverage) { // ~R1L give a base_uint<256> BOOST_CHECK((~~R1L >> 10) == (R1L >> 10)); BOOST_CHECK((~~R1L << 10) == (R1L << 10)); BOOST_CHECK(!(~~R1L < R1L)); BOOST_CHECK(~~R1L <= R1L); BOOST_CHECK(!(~~R1L > R1L)); BOOST_CHECK(~~R1L >= R1L); BOOST_CHECK(!(R1L < ~~R1L)); BOOST_CHECK(R1L <= ~~R1L); BOOST_CHECK(!(R1L > ~~R1L)); BOOST_CHECK(R1L >= ~~R1L); BOOST_CHECK(~~R1L + R2L == R1L + ~~R2L); BOOST_CHECK(~~R1L - R2L == R1L - ~~R2L); BOOST_CHECK(~R1L != R1L); BOOST_CHECK(R1L != ~R1L); uint8_t TmpArray[32]; CHECKBITWISEOPERATOR(~R1, R2, |) CHECKBITWISEOPERATOR(~R1, R2, ^) CHECKBITWISEOPERATOR(~R1, R2, &) CHECKBITWISEOPERATOR(R1, ~R2, |) CHECKBITWISEOPERATOR(R1, ~R2, ^) CHECKBITWISEOPERATOR(R1, ~R2, &) } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp index daff2b654..6c42c0607 100644 --- a/src/test/base32_tests.cpp +++ b/src/test/base32_tests.cpp @@ -1,27 +1,27 @@ -// Copyright (c) 2012-2015 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 #include #include BOOST_FIXTURE_TEST_SUITE(base32_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(base32_testvectors) { static const std::string vstrIn[] = {"", "f", "fo", "foo", "foob", "fooba", "foobar"}; static const std::string vstrOut[] = { "", "my======", "mzxq====", "mzxw6===", "mzxw6yq=", "mzxw6ytb", "mzxw6ytboi======"}; for (unsigned int i = 0; i < sizeof(vstrIn) / sizeof(vstrIn[0]); i++) { std::string strEnc = EncodeBase32(vstrIn[i]); BOOST_CHECK(strEnc == vstrOut[i]); std::string strDec = DecodeBase32(vstrOut[i]); BOOST_CHECK(strDec == vstrIn[i]); } } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index 265dc7ec8..86e62e6f2 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -1,77 +1,77 @@ -// 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. #include #include #include #include #include #include #include BOOST_FIXTURE_TEST_SUITE(base58_tests, BasicTestingSetup) // Goal: test low-level base58 encoding functionality BOOST_AUTO_TEST_CASE(base58_EncodeBase58) { UniValue tests = read_json(std::string(json_tests::base58_encode_decode, json_tests::base58_encode_decode + sizeof(json_tests::base58_encode_decode))); for (unsigned int idx = 0; idx < tests.size(); idx++) { UniValue test = tests[idx]; std::string strTest = test.write(); // Allow for extra stuff (useful for comments) if (test.size() < 2) { BOOST_ERROR("Bad test: " << strTest); continue; } std::vector sourcedata = ParseHex(test[0].get_str()); std::string base58string = test[1].get_str(); BOOST_CHECK_MESSAGE( EncodeBase58(sourcedata.data(), sourcedata.data() + sourcedata.size()) == base58string, strTest); } } // Goal: test low-level base58 decoding functionality BOOST_AUTO_TEST_CASE(base58_DecodeBase58) { UniValue tests = read_json(std::string(json_tests::base58_encode_decode, json_tests::base58_encode_decode + sizeof(json_tests::base58_encode_decode))); std::vector result; for (unsigned int idx = 0; idx < tests.size(); idx++) { UniValue test = tests[idx]; std::string strTest = test.write(); // Allow for extra stuff (useful for comments) if (test.size() < 2) { BOOST_ERROR("Bad test: " << strTest); continue; } std::vector expected = ParseHex(test[0].get_str()); std::string base58string = test[1].get_str(); BOOST_CHECK_MESSAGE(DecodeBase58(base58string, result), strTest); BOOST_CHECK_MESSAGE( result.size() == expected.size() && std::equal(result.begin(), result.end(), expected.begin()), strTest); } BOOST_CHECK(!DecodeBase58("invalid", result)); // check that DecodeBase58 skips whitespace, but still fails with unexpected // non-whitespace at the end. BOOST_CHECK(!DecodeBase58(" \t\n\v\f\r skip \r\f\v\n\t a", result)); BOOST_CHECK(DecodeBase58(" \t\n\v\f\r skip \r\f\v\n\t ", result)); std::vector expected = ParseHex("971a55"); BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end()); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp index 522405f21..3cde29b29 100644 --- a/src/test/base64_tests.cpp +++ b/src/test/base64_tests.cpp @@ -1,26 +1,26 @@ -// Copyright (c) 2011-2015 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 #include #include BOOST_FIXTURE_TEST_SUITE(base64_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(base64_testvectors) { static const std::string vstrIn[] = {"", "f", "fo", "foo", "foob", "fooba", "foobar"}; static const std::string vstrOut[] = { "", "Zg==", "Zm8=", "Zm9v", "Zm9vYg==", "Zm9vYmE=", "Zm9vYmFy"}; for (unsigned int i = 0; i < sizeof(vstrIn) / sizeof(vstrIn[0]); i++) { std::string strEnc = EncodeBase64(vstrIn[i]); BOOST_CHECK(strEnc == vstrOut[i]); std::string strDec = DecodeBase64(strEnc); BOOST_CHECK(strDec == vstrIn[i]); } } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp index 5caf53d88..04af71bef 100644 --- a/src/test/bip32_tests.cpp +++ b/src/test/bip32_tests.cpp @@ -1,300 +1,300 @@ -// Copyright (c) 2013-2015 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 #include #include #include #include #include #include #include #include #include #include struct TestDerivation { std::string pub; std::string prv; unsigned int nChild; }; struct TestVector { std::string strHexMaster; std::vector vDerive; explicit TestVector(std::string strHexMasterIn) : strHexMaster(strHexMasterIn) {} TestVector &operator()(std::string pub, std::string prv, unsigned int nChild) { vDerive.push_back(TestDerivation()); TestDerivation &der = vDerive.back(); der.pub = pub; der.prv = prv; der.nChild = nChild; return *this; } }; // clang-format off TestVector test1 = TestVector("000102030405060708090a0b0c0d0e0f") ("xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", 0x80000000) ("xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw", "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7", 1) ("xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ", "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs", 0x80000002) ("xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5", "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM", 2) ("xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV", "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334", 1000000000) ("xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy", "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76", 0); TestVector test2 = TestVector("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542") ("xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB", "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U", 0) ("xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH", "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt", 0xFFFFFFFF) ("xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a", "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9", 1) ("xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon", "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef", 0xFFFFFFFE) ("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL", "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc", 2) ("xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt", "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j", 0); TestVector test3 = TestVector("4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be") ("xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13", "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6", 0x80000000) ("xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y", "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L", 0); // clang-format on static void RunTest(const TestVector &test) { std::vector seed = ParseHex(test.strHexMaster); CExtKey key; CExtPubKey pubkey; key.SetSeed(seed.data(), seed.size()); pubkey = key.Neuter(); for (const TestDerivation &derive : test.vDerive) { uint8_t data[74]; key.Encode(data); pubkey.Encode(data); // Test private key BOOST_CHECK(EncodeExtKey(key) == derive.prv); // Ensure a base58 decoded key also matches BOOST_CHECK(DecodeExtKey(derive.prv) == key); // Test public key BOOST_CHECK(EncodeExtPubKey(pubkey) == derive.pub); // Ensure a base58 decoded pubkey also matches BOOST_CHECK(DecodeExtPubKey(derive.pub) == pubkey); // Derive new keys CExtKey keyNew; BOOST_CHECK(key.Derive(keyNew, derive.nChild)); CExtPubKey pubkeyNew = keyNew.Neuter(); if (!(derive.nChild & 0x80000000)) { // Compare with public derivation CExtPubKey pubkeyNew2; BOOST_CHECK(pubkey.Derive(pubkeyNew2, derive.nChild)); BOOST_CHECK(pubkeyNew == pubkeyNew2); } key = keyNew; pubkey = pubkeyNew; CDataStream ssPub(SER_DISK, CLIENT_VERSION); ssPub << pubkeyNew; BOOST_CHECK(ssPub.size() == 75); CDataStream ssPriv(SER_DISK, CLIENT_VERSION); ssPriv << keyNew; BOOST_CHECK(ssPriv.size() == 75); CExtPubKey pubCheck; CExtKey privCheck; ssPub >> pubCheck; ssPriv >> privCheck; BOOST_CHECK(pubCheck == pubkeyNew); BOOST_CHECK(privCheck == keyNew); } } BOOST_FIXTURE_TEST_SUITE(bip32_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(bip32_test1) { RunTest(test1); } BOOST_AUTO_TEST_CASE(bip32_test2) { RunTest(test2); } BOOST_AUTO_TEST_CASE(bip32_test3) { RunTest(test3); } bool check_key_size_message(const std::runtime_error &e) { BOOST_CHECK_EQUAL(e.what(), "Invalid extended key size\n"); return true; } BOOST_AUTO_TEST_CASE(bip32_serialization) { std::vector pubkeys{ "013442193e8000000047fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad1628" "2c7ae6236141035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c70" "6cfccc56", "025c1bd648000000012a7857631386ba23dacac34180dd1983734e444fdbf774041578" "e9b6adb37c1903501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bed" "b3cd711c", "03bef5a2f98000000204466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3" "ff6ec7b1503f0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a78" "96ee8dc2", "04ee7ab90c00000002cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac12" "75ac822a3edd02e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e358045" "60741d29", "05d880d7d83b9aca00c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548" "a8b078e65e9e022a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5" "a48f7011", "06d69aa10200000000739379b40b549fdb7f2439c028dac3192d4706deec3f0fef6816" "ea36c8fc3fda028817473b2e81a20b60a24fc7a0d7869368ebc36740cfe08a18a19a9d" "dafae67c", "01bd16bee500000000f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7" "412f232f7c9c02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22" "a98d12ea", "025a61ff8effffffffbe17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b3854" "7f585c9a37d903c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666a" "bc0a5c3b", "03d8ab493700000001f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c92" "7eb246fb38cb03a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e78" "1a7df5b9", "0478412e3afffffffe637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06" "cc29a65a0e2902d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806ca" "fb0301f0", "0531a507b8000000029452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58" "eedf394ed271024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c" "7afe1f9c", "0626132fdb0000000005bcc50a4c1bbfa6d982ae1f410f88ddcbacad781b11b8790c86" "f49cdf9e77b0031c0517fff3d483f06ca769bd2326bf30aca1c4de278e676e6ef760c3" "301244c6", "0141d63b5080000000e5fea12a97b927fc9dc3d2cb0d1ea1cf50aa5a1fdc1f933e8906" "bb38df3377bd026557fdda1d5d43d79611f784780471f086d58e8126b8c40acb82272a" "7712e7f2", "02c61368bb000000007c63ec0429a7324b76014ad222a32b7fdd3ae8755d0d2b2e3dfb" "5ede9787af990379e45b3cf75f9c5f9befd8e9506fb962f6a9d185ac87001ec44a8d3d" "f8d4a9e3", }; for (const std::string &hex : pubkeys) { CDataStream ss(SER_DISK, CLIENT_VERSION); ss << ParseHex(hex); BOOST_CHECK(ss.size() == 75); CExtPubKey pubkey; BOOST_CHECK_NO_THROW(ss >> pubkey); ss << ParseHex(hex + "00"); BOOST_CHECK(ss.size() == 76); BOOST_CHECK_EXCEPTION(ss >> pubkey, std::runtime_error, check_key_size_message); ss.clear(); ss << ParseHex(hex.substr(0, hex.size() - 1)); BOOST_CHECK(ss.size() == 74); BOOST_CHECK_EXCEPTION(ss >> pubkey, std::runtime_error, check_key_size_message); } std::vector privkeys{ "013442193e8000000047fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad1628" "2c7ae623614100edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d9" "11a0afea", "025c1bd648000000012a7857631386ba23dacac34180dd1983734e444fdbf774041578" "e9b6adb37c19003c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de931" "9dc93368", "03bef5a2f98000000204466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3" "ff6ec7b1503f00cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59" "fa424dca", "04ee7ab90c00000002cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac12" "75ac822a3edd000f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a" "2a764ef4", "05d880d7d83b9aca00c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548" "a8b078e65e9e00471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6" "c3e6e7c8", "06d69aa10200000000739379b40b549fdb7f2439c028dac3192d4706deec3f0fef6816" "ea36c8fc3fda00996cbe292e59ce1c8ee257522ce969b9faa413f7e9aa4a8785b8f574" "e0e2f061", "01bd16bee500000000f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7" "412f232f7c9c00abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f" "15ac7e1e", "025a61ff8effffffffbe17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b3854" "7f585c9a37d900877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18f" "d52e6e93", "03d8ab493700000001f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c92" "7eb246fb38cb00704addf544a06e5ee4bea37098463c23613da32020d604506da8c051" "8e1da4b7", "0478412e3afffffffe637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06" "cc29a65a0e2900f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b" "247d6a2d", "0531a507b8000000029452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58" "eedf394ed27100bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a484" "2125ac23", "0626132fdb0000000005bcc50a4c1bbfa6d982ae1f410f88ddcbacad781b11b8790c86" "f49cdf9e77b0004b7e8b1aa263519f7fbed001d5b0c4a5fdac81db8abe14c327e2f534" "92e55fa7", "0141d63b5080000000e5fea12a97b927fc9dc3d2cb0d1ea1cf50aa5a1fdc1f933e8906" "bb38df3377bd00491f7a2eebc7b57028e0d3faa0acda02e75c33b03c48fb288c41e2ea" "44e1daef", "02c61368bb000000007c63ec0429a7324b76014ad222a32b7fdd3ae8755d0d2b2e3dfb" "5ede9787af9900129ee831061c31be7d636fc0402fd2299855f40015a2c60b2e5755c5" "7270460d", }; for (const std::string &hex : privkeys) { CDataStream ss(SER_DISK, CLIENT_VERSION); ss << ParseHex(hex); BOOST_CHECK(ss.size() == 75); CExtKey privkey; BOOST_CHECK_NO_THROW(ss >> privkey); ss << ParseHex(hex + "00"); BOOST_CHECK(ss.size() == 76); BOOST_CHECK_EXCEPTION(ss >> privkey, std::runtime_error, check_key_size_message); ss.clear(); ss << ParseHex(hex.substr(0, hex.size() - 1)); BOOST_CHECK(ss.size() == 74); BOOST_CHECK_EXCEPTION(ss >> privkey, std::runtime_error, check_key_size_message); } } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp index 352dabac5..f739d4af8 100644 --- a/src/test/blockencodings_tests.cpp +++ b/src/test/blockencodings_tests.cpp @@ -1,489 +1,489 @@ -// 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. #include #include #include #include #include #include #include #include #include #include static std::vector> extra_txn; struct RegtestingSetup : public TestingSetup { RegtestingSetup() : TestingSetup(CBaseChainParams::REGTEST) {} }; BOOST_FIXTURE_TEST_SUITE(blockencodings_tests, RegtestingSetup) static COutPoint InsecureRandOutPoint() { return COutPoint(TxId(InsecureRand256()), 0); } static CBlock BuildBlockTestCase() { CBlock block; CMutableTransaction tx; tx.vin.resize(1); tx.vin[0].scriptSig.resize(10); tx.vout.resize(1); tx.vout[0].nValue = 42 * SATOSHI; block.vtx.resize(3); block.vtx[0] = MakeTransactionRef(tx); block.nVersion = 42; block.hashPrevBlock = BlockHash(InsecureRand256()); block.nBits = 0x207fffff; tx.vin[0].prevout = InsecureRandOutPoint(); block.vtx[1] = MakeTransactionRef(tx); tx.vin.resize(10); for (size_t i = 0; i < tx.vin.size(); i++) { tx.vin[i].prevout = InsecureRandOutPoint(); } block.vtx[2] = MakeTransactionRef(tx); bool mutated; block.hashMerkleRoot = BlockMerkleRoot(block, &mutated); assert(!mutated); GlobalConfig config; const Consensus::Params ¶ms = config.GetChainParams().GetConsensus(); while (!CheckProofOfWork(block.GetHash(), block.nBits, params)) { ++block.nNonce; } return block; } // BOOST_CHECK_EXCEPTION predicates to check the exception message class HasReason { public: HasReason(const std::string &reason) : m_reason(reason) {} bool operator()(const std::exception &e) const { return std::string(e.what()).find(m_reason) != std::string::npos; }; private: const std::string m_reason; }; // Number of shared use_counts we expect for a tx we haven't touched // (block + mempool + our copy from the GetSharedTx call) constexpr long SHARED_TX_OFFSET{3}; BOOST_AUTO_TEST_CASE(SimpleRoundTripTest) { CTxMemPool pool; TestMemPoolEntryHelper entry; CBlock block(BuildBlockTestCase()); LOCK2(cs_main, pool.cs); pool.addUnchecked(entry.FromTx(block.vtx[2])); BOOST_CHECK_EQUAL( pool.mapTx.find(block.vtx[2]->GetId())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0); // Do a simple ShortTxIDs RT { CBlockHeaderAndShortTxIDs shortIDs(block); CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << shortIDs; CBlockHeaderAndShortTxIDs shortIDs2; stream >> shortIDs2; PartiallyDownloadedBlock partialBlock(GetConfig(), &pool); BOOST_CHECK(partialBlock.InitData(shortIDs2, extra_txn) == READ_STATUS_OK); BOOST_CHECK(partialBlock.IsTxAvailable(0)); BOOST_CHECK(!partialBlock.IsTxAvailable(1)); BOOST_CHECK(partialBlock.IsTxAvailable(2)); BOOST_CHECK_EQUAL( pool.mapTx.find(block.vtx[2]->GetId())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1); size_t poolSize = pool.size(); pool.removeRecursive(*block.vtx[2]); BOOST_CHECK_EQUAL(pool.size(), poolSize - 1); CBlock block2; { // No transactions. PartiallyDownloadedBlock tmp = partialBlock; BOOST_CHECK(partialBlock.FillBlock(block2, {}) == READ_STATUS_INVALID); partialBlock = tmp; } // Wrong transaction { // Current implementation doesn't check txn here, but don't require // that. PartiallyDownloadedBlock tmp = partialBlock; partialBlock.FillBlock(block2, {block.vtx[2]}); partialBlock = tmp; } bool mutated; BOOST_CHECK(block.hashMerkleRoot != BlockMerkleRoot(block2, &mutated)); CBlock block3; BOOST_CHECK(partialBlock.FillBlock(block3, {block.vtx[1]}) == READ_STATUS_OK); BOOST_CHECK_EQUAL(block.GetHash().ToString(), block3.GetHash().ToString()); BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block3, &mutated).ToString()); BOOST_CHECK(!mutated); } } class TestHeaderAndShortIDs { // Utility to encode custom CBlockHeaderAndShortTxIDs public: CBlockHeader header; uint64_t nonce; std::vector shorttxids; std::vector prefilledtxn; explicit TestHeaderAndShortIDs(const CBlockHeaderAndShortTxIDs &orig) { CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << orig; stream >> *this; } explicit TestHeaderAndShortIDs(const CBlock &block) : TestHeaderAndShortIDs(CBlockHeaderAndShortTxIDs(block)) {} uint64_t GetShortID(const TxHash &txhash) const { CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << *this; CBlockHeaderAndShortTxIDs base; stream >> base; return base.GetShortID(txhash); } ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream &s, Operation ser_action) { READWRITE(header); READWRITE(nonce); size_t shorttxids_size = shorttxids.size(); READWRITE(VARINT(shorttxids_size)); shorttxids.resize(shorttxids_size); for (size_t i = 0; i < shorttxids.size(); i++) { uint32_t lsb = shorttxids[i] & 0xffffffff; uint16_t msb = (shorttxids[i] >> 32) & 0xffff; READWRITE(lsb); READWRITE(msb); shorttxids[i] = (uint64_t(msb) << 32) | uint64_t(lsb); } READWRITE(prefilledtxn); } }; BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest) { CTxMemPool pool; TestMemPoolEntryHelper entry; CBlock block(BuildBlockTestCase()); LOCK2(cs_main, pool.cs); pool.addUnchecked(entry.FromTx(block.vtx[2])); BOOST_CHECK_EQUAL( pool.mapTx.find(block.vtx[2]->GetId())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0); TxId txid; // Test with pre-forwarding tx 1, but not coinbase { TestHeaderAndShortIDs shortIDs(block); shortIDs.prefilledtxn.resize(1); shortIDs.prefilledtxn[0] = {1, block.vtx[1]}; shortIDs.shorttxids.resize(2); shortIDs.shorttxids[0] = shortIDs.GetShortID(block.vtx[0]->GetHash()); shortIDs.shorttxids[1] = shortIDs.GetShortID(block.vtx[2]->GetHash()); CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << shortIDs; CBlockHeaderAndShortTxIDs shortIDs2; stream >> shortIDs2; PartiallyDownloadedBlock partialBlock(GetConfig(), &pool); BOOST_CHECK(partialBlock.InitData(shortIDs2, extra_txn) == READ_STATUS_OK); BOOST_CHECK(!partialBlock.IsTxAvailable(0)); BOOST_CHECK(partialBlock.IsTxAvailable(1)); BOOST_CHECK(partialBlock.IsTxAvailable(2)); // +1 because of partialBlock BOOST_CHECK_EQUAL( pool.mapTx.find(block.vtx[2]->GetId())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1); CBlock block2; { // No transactions. PartiallyDownloadedBlock tmp = partialBlock; BOOST_CHECK(partialBlock.FillBlock(block2, {}) == READ_STATUS_INVALID); partialBlock = tmp; } // Wrong transaction { // Current implementation doesn't check txn here, but don't require // that. PartiallyDownloadedBlock tmp = partialBlock; partialBlock.FillBlock(block2, {block.vtx[1]}); partialBlock = tmp; } // +2 because of partialBlock and block2 BOOST_CHECK_EQUAL( pool.mapTx.find(block.vtx[2]->GetId())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 2); bool mutated; BOOST_CHECK(block.hashMerkleRoot != BlockMerkleRoot(block2, &mutated)); CBlock block3; PartiallyDownloadedBlock partialBlockCopy = partialBlock; BOOST_CHECK(partialBlock.FillBlock(block3, {block.vtx[0]}) == READ_STATUS_OK); BOOST_CHECK_EQUAL(block.GetHash().ToString(), block3.GetHash().ToString()); BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block3, &mutated).ToString()); BOOST_CHECK(!mutated); // +3 because of partialBlock and block2 and block3 BOOST_CHECK_EQUAL( pool.mapTx.find(block.vtx[2]->GetId())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 3); txid = block.vtx[2]->GetId(); block.vtx.clear(); block2.vtx.clear(); block3.vtx.clear(); // + 1 because of partialBlock; -1 because of block. BOOST_CHECK_EQUAL(pool.mapTx.find(txid)->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1 - 1); } // -1 because of block BOOST_CHECK_EQUAL(pool.mapTx.find(txid)->GetSharedTx().use_count(), SHARED_TX_OFFSET - 1); } BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest) { CTxMemPool pool; TestMemPoolEntryHelper entry; CBlock block(BuildBlockTestCase()); LOCK2(cs_main, pool.cs); pool.addUnchecked(entry.FromTx(block.vtx[1])); BOOST_CHECK_EQUAL( pool.mapTx.find(block.vtx[1]->GetId())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0); TxId txid; // Test with pre-forwarding coinbase + tx 2 with tx 1 in mempool { TestHeaderAndShortIDs shortIDs(block); shortIDs.prefilledtxn.resize(2); shortIDs.prefilledtxn[0] = {0, block.vtx[0]}; // id == 1 as it is 1 after index 1 shortIDs.prefilledtxn[1] = {1, block.vtx[2]}; shortIDs.shorttxids.resize(1); shortIDs.shorttxids[0] = shortIDs.GetShortID(block.vtx[1]->GetHash()); CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << shortIDs; CBlockHeaderAndShortTxIDs shortIDs2; stream >> shortIDs2; PartiallyDownloadedBlock partialBlock(GetConfig(), &pool); BOOST_CHECK(partialBlock.InitData(shortIDs2, extra_txn) == READ_STATUS_OK); BOOST_CHECK(partialBlock.IsTxAvailable(0)); BOOST_CHECK(partialBlock.IsTxAvailable(1)); BOOST_CHECK(partialBlock.IsTxAvailable(2)); BOOST_CHECK_EQUAL( pool.mapTx.find(block.vtx[1]->GetId())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1); CBlock block2; PartiallyDownloadedBlock partialBlockCopy = partialBlock; BOOST_CHECK(partialBlock.FillBlock(block2, {}) == READ_STATUS_OK); BOOST_CHECK_EQUAL(block.GetHash().ToString(), block2.GetHash().ToString()); bool mutated; BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block2, &mutated).ToString()); BOOST_CHECK(!mutated); txid = block.vtx[1]->GetId(); block.vtx.clear(); block2.vtx.clear(); // + 1 because of partialBlock; -1 because of block. BOOST_CHECK_EQUAL(pool.mapTx.find(txid)->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1 - 1); } // -1 because of block BOOST_CHECK_EQUAL(pool.mapTx.find(txid)->GetSharedTx().use_count(), SHARED_TX_OFFSET - 1); } BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest) { CTxMemPool pool; CMutableTransaction coinbase; coinbase.vin.resize(1); coinbase.vin[0].scriptSig.resize(10); coinbase.vout.resize(1); coinbase.vout[0].nValue = 42 * SATOSHI; CBlock block; block.vtx.resize(1); block.vtx[0] = MakeTransactionRef(std::move(coinbase)); block.nVersion = 42; block.hashPrevBlock = BlockHash(InsecureRand256()); block.nBits = 0x207fffff; bool mutated; block.hashMerkleRoot = BlockMerkleRoot(block, &mutated); assert(!mutated); GlobalConfig config; const Consensus::Params ¶ms = config.GetChainParams().GetConsensus(); while (!CheckProofOfWork(block.GetHash(), block.nBits, params)) { ++block.nNonce; } // Test simple header round-trip with only coinbase { CBlockHeaderAndShortTxIDs shortIDs(block); CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << shortIDs; CBlockHeaderAndShortTxIDs shortIDs2; stream >> shortIDs2; PartiallyDownloadedBlock partialBlock(GetConfig(), &pool); BOOST_CHECK(partialBlock.InitData(shortIDs2, extra_txn) == READ_STATUS_OK); BOOST_CHECK(partialBlock.IsTxAvailable(0)); CBlock block2; std::vector vtx_missing; BOOST_CHECK(partialBlock.FillBlock(block2, vtx_missing) == READ_STATUS_OK); BOOST_CHECK_EQUAL(block.GetHash().ToString(), block2.GetHash().ToString()); BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block2, &mutated).ToString()); BOOST_CHECK(!mutated); } } BOOST_AUTO_TEST_CASE(TransactionsRequestSerializationTest) { BlockTransactionsRequest req1; req1.blockhash = BlockHash(InsecureRand256()); req1.indices.resize(4); req1.indices[0] = 0; req1.indices[1] = 1; req1.indices[2] = 3; req1.indices[3] = 4; CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << req1; BlockTransactionsRequest req2; stream >> req2; BOOST_CHECK_EQUAL(req1.blockhash.ToString(), req2.blockhash.ToString()); BOOST_CHECK_EQUAL(req1.indices.size(), req2.indices.size()); BOOST_CHECK_EQUAL(req1.indices[0], req2.indices[0]); BOOST_CHECK_EQUAL(req1.indices[1], req2.indices[1]); BOOST_CHECK_EQUAL(req1.indices[2], req2.indices[2]); BOOST_CHECK_EQUAL(req1.indices[3], req2.indices[3]); } BOOST_AUTO_TEST_CASE(TransactionsRequestDeserializationMaxTest) { // Check that the highest legal index is decoded correctly BlockTransactionsRequest req0; req0.blockhash = BlockHash(InsecureRand256()); req0.indices.resize(1); using indiceType = decltype(req0.indices)::value_type; static_assert(MAX_SIZE < std::numeric_limits::max(), "The max payload size cannot fit into the indice type"); req0.indices[0] = MAX_SIZE; CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << req0; BlockTransactionsRequest req1; stream >> req1; BOOST_CHECK_EQUAL(req0.indices.size(), req1.indices.size()); BOOST_CHECK_EQUAL(req0.indices[0], req1.indices[0]); req0.indices[0] += 1; stream << req0; BlockTransactionsRequest req2; BOOST_CHECK_EXCEPTION(stream >> req2, std::ios_base::failure, HasReason("ReadCompactSize(): size too large")); } BOOST_AUTO_TEST_CASE(TransactionsRequestDeserializationOverflowTest) { // Any set of index deltas that starts with N values that sum to // (0x100000000 - 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. This can only occur if MAX_SIZE is greater than the // maximum value for that the indice type can handle. BlockTransactionsRequest req0; req0.blockhash = BlockHash(InsecureRand256()); req0.indices.resize(3); using indiceType = decltype(req0.indices)::value_type; static_assert(std::is_same::value, "This test expects the indice type to be an uint32_t"); req0.indices[0] = 0x7000; req0.indices[1] = 0x100000000 - 0x7000 - 2; req0.indices[2] = 0; CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << req0.blockhash; WriteCompactSize(stream, req0.indices.size()); WriteCompactSize(stream, req0.indices[0]); WriteCompactSize(stream, req0.indices[1]); WriteCompactSize(stream, req0.indices[2]); BlockTransactionsRequest req1; // If MAX_SIZE is the limiting factor, the deserialization should throw. // Otherwise make sure that the overflow edge-case is under control. BOOST_CHECK_EXCEPTION(stream >> req1, std::ios_base::failure, HasReason((MAX_SIZE < req0.indices[1]) ? "ReadCompactSize(): size too large" : "indices overflowed 32 bits")); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/blockfilter_tests.cpp b/src/test/blockfilter_tests.cpp index 44daf9757..ef8c72ea8 100644 --- a/src/test/blockfilter_tests.cpp +++ b/src/test/blockfilter_tests.cpp @@ -1,194 +1,194 @@ -// 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. #include #include #include #include #include #include #include #include #include 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 ¶ms = 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[3]; // First two are outputs on a single transaction. included_scripts[0] << std::vector(0, 65) << OP_CHECKSIG; included_scripts[1] << OP_DUP << OP_HASH160 << std::vector(1, 20) << OP_EQUALVERIFY << OP_CHECKSIG; // Third is an output on in a second transaction. included_scripts[2] << OP_1 << std::vector(2, 33) << OP_1 << OP_CHECKMULTISIG; // Last two are spent by a single transaction. included_scripts[3] << OP_0 << std::vector(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(4, 40); // This script is not related to the block at all. excluded_scripts[1] << std::vector(5, 33) << OP_CHECKSIG; CMutableTransaction tx_1; tx_1.vout.emplace_back(100 * SATOSHI, included_scripts[0]); tx_1.vout.emplace_back(200 * SATOSHI, included_scripts[1]); CMutableTransaction tx_2; tx_2.vout.emplace_back(300 * SATOSHI, included_scripts[2]); tx_2.vout.emplace_back(0 * SATOSHI, excluded_scripts[0]); // Script is empty tx_2.vout.emplace_back(400 * SATOSHI, excluded_scripts[2]); 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 * SATOSHI, included_scripts[3]), 1000, true); block_undo.vtxundo.back().vprevout.emplace_back( CTxOut(600 * SATOSHI, included_scripts[4]), 10000, false); block_undo.vtxundo.back().vprevout.emplace_back( CTxOut(700 * SATOSHI, excluded_scripts[2]), 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(block_filter.GetFilterType() == block_filter2.GetFilterType()); BOOST_CHECK(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(default_ctor_block_filter_1.GetFilterType() == default_ctor_block_filter_2.GetFilterType()); BOOST_CHECK(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 (size_t 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; } size_t 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 (size_t ii = 0; ii < prev_scripts.size(); ii++) { std::vector raw_script = ParseHex(prev_scripts[ii].get_str()); CTxOut txout(0 * SATOSHI, 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 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_SUITE_END() diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index 32a7d9506..5bfcbb8a6 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -1,1172 +1,1172 @@ -// Copyright (c) 2012-2016 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include BOOST_FIXTURE_TEST_SUITE(bloom_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize) { CBloomFilter filter(3, 0.01, 0, BLOOM_UPDATE_ALL); filter.insert(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")); BOOST_CHECK_MESSAGE( filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter doesn't contain just-inserted object!"); // One bit different in first byte BOOST_CHECK_MESSAGE( !filter.contains(ParseHex("19108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter contains something it shouldn't!"); filter.insert(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee")); BOOST_CHECK_MESSAGE( filter.contains(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee")), "Bloom filter doesn't contain just-inserted object (2)!"); filter.insert(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5")); BOOST_CHECK_MESSAGE( filter.contains(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5")), "Bloom filter doesn't contain just-inserted object (3)!"); CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << filter; std::vector vch = ParseHex("03614e9b050000000000000001"); std::vector expected(vch.size()); for (size_t i = 0; i < vch.size(); i++) { expected[i] = (char)vch[i]; } BOOST_CHECK_EQUAL_COLLECTIONS(stream.begin(), stream.end(), expected.begin(), expected.end()); BOOST_CHECK_MESSAGE( filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter doesn't contain just-inserted object!"); filter.clear(); BOOST_CHECK_MESSAGE( !filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter should be empty!"); } BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize_with_tweak) { // Same test as bloom_create_insert_serialize, but we add a nTweak of 100 CBloomFilter filter(3, 0.01, 2147483649UL, BLOOM_UPDATE_ALL); filter.insert(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")); BOOST_CHECK_MESSAGE( filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter doesn't contain just-inserted object!"); // One bit different in first byte BOOST_CHECK_MESSAGE( !filter.contains(ParseHex("19108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter contains something it shouldn't!"); filter.insert(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee")); BOOST_CHECK_MESSAGE( filter.contains(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee")), "Bloom filter doesn't contain just-inserted object (2)!"); filter.insert(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5")); BOOST_CHECK_MESSAGE( filter.contains(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5")), "Bloom filter doesn't contain just-inserted object (3)!"); CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << filter; std::vector vch = ParseHex("03ce4299050000000100008001"); std::vector expected(vch.size()); for (size_t i = 0; i < vch.size(); i++) { expected[i] = (char)vch[i]; } BOOST_CHECK_EQUAL_COLLECTIONS(stream.begin(), stream.end(), expected.begin(), expected.end()); } BOOST_AUTO_TEST_CASE(bloom_create_insert_key) { std::string strSecret = std::string("5Kg1gnAjaLfKiwhhPpGS3QfRg2m6awQvaj98JCZBZQ5SuS2F15C"); CKey key = DecodeSecret(strSecret); CPubKey pubkey = key.GetPubKey(); std::vector vchPubKey(pubkey.begin(), pubkey.end()); CBloomFilter filter(2, 0.001, 0, BLOOM_UPDATE_ALL); filter.insert(vchPubKey); uint160 hash = pubkey.GetID(); filter.insert(std::vector(hash.begin(), hash.end())); CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << filter; std::vector vch = ParseHex("038fc16b080000000000000001"); std::vector expected(vch.size()); for (size_t i = 0; i < vch.size(); i++) { expected[i] = (char)vch[i]; } BOOST_CHECK_EQUAL_COLLECTIONS(stream.begin(), stream.end(), expected.begin(), expected.end()); } BOOST_AUTO_TEST_CASE(bloom_match) { // Random real transaction // (b4749f017444b051c44dfd2720e88f314ff94f3dd6d56d40ef65854fcd7fff6b) CDataStream stream( ParseHex("01000000010b26e9b7735eb6aabdf358bab62f9816a21ba9ebdb719d5299e" "88607d722c190000000008b4830450220070aca44506c5cef3a16ed519d7c" "3c39f8aab192c4e1c90d065f37b8a4af6141022100a8e160b856c2d43d27d" "8fba71e5aef6405b8643ac4cb7cb3c462aced7f14711a0141046d11fee51b" "0e60666d5049a9101a72741df480b96ee26488a4d3466b95c9a40ac5eeef8" "7e10a5cd336c19a84565f80fa6c547957b7700ff4dfbdefe76036c339ffff" "ffff021bff3d11000000001976a91404943fdd508053c75000106d3bc6e27" "54dbcff1988ac2f15de00000000001976a914a266436d2965547608b9e15d" "9032a7b9d64fa43188ac00000000"), SER_DISK, CLIENT_VERSION); CTransaction tx(deserialize, stream); // and one which spends it // (e2769b09e784f32f62ef849763d4f45b98e07ba658647343b915ff832b110436) uint8_t ch[] = { 0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0xff, 0x7f, 0xcd, 0x4f, 0x85, 0x65, 0xef, 0x40, 0x6d, 0xd5, 0xd6, 0x3d, 0x4f, 0xf9, 0x4f, 0x31, 0x8f, 0xe8, 0x20, 0x27, 0xfd, 0x4d, 0xc4, 0x51, 0xb0, 0x44, 0x74, 0x01, 0x9f, 0x74, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x49, 0x30, 0x46, 0x02, 0x21, 0x00, 0xda, 0x0d, 0xc6, 0xae, 0xce, 0xfe, 0x1e, 0x06, 0xef, 0xdf, 0x05, 0x77, 0x37, 0x57, 0xde, 0xb1, 0x68, 0x82, 0x09, 0x30, 0xe3, 0xb0, 0xd0, 0x3f, 0x46, 0xf5, 0xfc, 0xf1, 0x50, 0xbf, 0x99, 0x0c, 0x02, 0x21, 0x00, 0xd2, 0x5b, 0x5c, 0x87, 0x04, 0x00, 0x76, 0xe4, 0xf2, 0x53, 0xf8, 0x26, 0x2e, 0x76, 0x3e, 0x2d, 0xd5, 0x1e, 0x7f, 0xf0, 0xbe, 0x15, 0x77, 0x27, 0xc4, 0xbc, 0x42, 0x80, 0x7f, 0x17, 0xbd, 0x39, 0x01, 0x41, 0x04, 0xe6, 0xc2, 0x6e, 0xf6, 0x7d, 0xc6, 0x10, 0xd2, 0xcd, 0x19, 0x24, 0x84, 0x78, 0x9a, 0x6c, 0xf9, 0xae, 0xa9, 0x93, 0x0b, 0x94, 0x4b, 0x7e, 0x2d, 0xb5, 0x34, 0x2b, 0x9d, 0x9e, 0x5b, 0x9f, 0xf7, 0x9a, 0xff, 0x9a, 0x2e, 0xe1, 0x97, 0x8d, 0xd7, 0xfd, 0x01, 0xdf, 0xc5, 0x22, 0xee, 0x02, 0x28, 0x3d, 0x3b, 0x06, 0xa9, 0xd0, 0x3a, 0xcf, 0x80, 0x96, 0x96, 0x8d, 0x7d, 0xbb, 0x0f, 0x91, 0x78, 0xff, 0xff, 0xff, 0xff, 0x02, 0x8b, 0xa7, 0x94, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xba, 0xde, 0xec, 0xfd, 0xef, 0x05, 0x07, 0x24, 0x7f, 0xc8, 0xf7, 0x42, 0x41, 0xd7, 0x3b, 0xc0, 0x39, 0x97, 0x2d, 0x7b, 0x88, 0xac, 0x40, 0x94, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xc1, 0x09, 0x32, 0x48, 0x3f, 0xec, 0x93, 0xed, 0x51, 0xf5, 0xfe, 0x95, 0xe7, 0x25, 0x59, 0xf2, 0xcc, 0x70, 0x43, 0xf9, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00}; std::vector vch(ch, ch + sizeof(ch) - 1); CDataStream spendStream(vch, SER_DISK, CLIENT_VERSION); CTransaction spendingTx(deserialize, spendStream); CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL); filter.insert(uint256S( "0xb4749f017444b051c44dfd2720e88f314ff94f3dd6d56d40ef65854fcd7fff6b")); BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match tx hash"); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); // byte-reversed tx hash filter.insert(ParseHex( "6bff7fcd4f8565ef406dd5d63d4ff94f318fe82027fd4dc451b04474019f74b4")); BOOST_CHECK_MESSAGE( filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match manually serialized tx hash"); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); filter.insert(ParseHex("30450220070aca44506c5cef3a16ed519d7c3c39f8aab192c4e" "1c90d065f37b8a4af6141022100a8e160b856c2d43d27d8fba7" "1e5aef6405b8643ac4cb7cb3c462aced7f14711a01")); BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match input signature"); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); filter.insert(ParseHex("046d11fee51b0e60666d5049a9101a72741df480b96ee26488a" "4d3466b95c9a40ac5eeef87e10a5cd336c19a84565f80fa6c54" "7957b7700ff4dfbdefe76036c339")); BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match input pub key"); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); filter.insert(ParseHex("04943fdd508053c75000106d3bc6e2754dbcff19")); BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match output address"); BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(spendingTx), "Simple Bloom filter didn't add output"); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); filter.insert(ParseHex("04943fdd508053c75000106d3bc6e2754dbcff19")); BOOST_CHECK_MESSAGE(filter.MatchAndInsertOutputs(tx), "Simple Bloom filter didn't match output address"); BOOST_CHECK_MESSAGE(!filter.MatchAndInsertOutputs(spendingTx), "Simple Bloom filter matched unrelated output"); BOOST_CHECK_MESSAGE(filter.MatchInputs(spendingTx), "Simple Bloom filter didn't add output"); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); filter.insert(ParseHex("a266436d2965547608b9e15d9032a7b9d64fa431")); BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match output address"); const TxId txid(uint256S( "0x90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b")); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); filter.insert(COutPoint(txid, 0)); BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match COutPoint"); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); COutPoint prevOutPoint(txid, 0); { std::vector data(32 + sizeof(uint32_t)); memcpy(data.data(), prevOutPoint.GetTxId().begin(), 32); uint32_t n = prevOutPoint.GetN(); memcpy(data.data() + 32, &n, sizeof(uint32_t)); filter.insert(data); } BOOST_CHECK_MESSAGE( filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match manually serialized COutPoint"); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); filter.insert(uint256S( "00000009e784f32f62ef849763d4f45b98e07ba658647343b915ff832b110436")); BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched random tx hash"); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); filter.insert(ParseHex("0000006d2965547608b9e15d9032a7b9d64fa431")); BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched random address"); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); filter.insert(COutPoint(txid, 1)); BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched COutPoint for an output " "we didn't care about"); const TxId lowtxid(uint256S( "0x000000d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b")); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); filter.insert(COutPoint(lowtxid, 0)); BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched COutPoint for an output " "we didn't care about"); } BOOST_AUTO_TEST_CASE(merkle_block_1) { CBlock block = getBlock13b8a(); CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL); // Match the last transaction filter.insert(uint256S( "0x74d681e0e03bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20")); CMerkleBlock merkleBlock(block, filter); BOOST_CHECK_EQUAL(merkleBlock.header.GetHash().GetHex(), block.GetHash().GetHex()); BOOST_CHECK_EQUAL(merkleBlock.vMatchedTxn.size(), 1U); std::pair pair = merkleBlock.vMatchedTxn[0]; BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256S("0x74d681e0e03bafa802c8aa084379aa98d9fcd632ddc2ed9782b" "586ec87451f20")); BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 8); std::vector vMatched; std::vector vIndex; BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot); BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size()); for (size_t i = 0; i < vMatched.size(); i++) { BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second); } // Also match the 8th transaction filter.insert(uint256S( "0xdd1fd2a6fc16404faf339881a90adbde7f4f728691ac62e8f168809cdfae1053")); merkleBlock = CMerkleBlock(block, filter); BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash()); BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 2); BOOST_CHECK(merkleBlock.vMatchedTxn[1] == pair); BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256S("0xdd1fd2a6fc16404faf339881a90adbde7f4f728691ac62e8f16" "8809cdfae1053")); BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 7); BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot); BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size()); for (size_t i = 0; i < vMatched.size(); i++) { BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second); } } BOOST_AUTO_TEST_CASE(merkle_block_2) { // Random real block // (000000005a4ded781e667e06ceefafb71410b511fe0d5adc3e5a27ecbec34ae6) // With 4 txes CBlock block; CDataStream stream( ParseHex( "0100000075616236cc2126035fadb38deb65b9102cc2c41c09cdf29fc051906800" "000000fe7d5e12ef0ff901f6050211249919b1c0653771832b3a80c66cea42847f" "0ae1d4d26e49ffff001d00f0a44104010000000100000000000000000000000000" "00000000000000000000000000000000000000ffffffff0804ffff001d029105ff" "ffffff0100f2052a010000004341046d8709a041d34357697dfcb30a9d05900a62" "94078012bf3bb09c6f9b525f1d16d5503d7905db1ada9501446ea00728668fc571" "9aa80be2fdfc8a858a4dbdd4fbac00000000010000000255605dc6f5c3dc148b6d" "a58442b0b2cd422be385eab2ebea4119ee9c268d28350000000049483045022100" "aa46504baa86df8a33b1192b1b9367b4d729dc41e389f2c04f3e5c7f0559aae702" "205e82253a54bf5c4f65b7428551554b2045167d6d206dfe6a2e198127d3f7df15" "01ffffffff55605dc6f5c3dc148b6da58442b0b2cd422be385eab2ebea4119ee9c" "268d2835010000004847304402202329484c35fa9d6bb32a55a70c0982f606ce0e" "3634b69006138683bcd12cbb6602200c28feb1e2555c3210f1dddb299738b4ff8b" "be9667b68cb8764b5ac17b7adf0001ffffffff0200e1f505000000004341046a07" "65b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a" "68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00180d" "8f000000004341044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad7" "69f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cf" "c617c0ea45afac0000000001000000025f9a06d3acdceb56be1bfeaa3e8a25e62d" "182fa24fefe899d1c17f1dad4c2028000000004847304402205d6058484157235b" "06028c30736c15613a28bdb768ee628094ca8b0030d4d6eb0220328789c9a2ec27" "ddaec0ad5ef58efded42e6ea17c2e1ce838f3d6913f5e95db601ffffffff5f9a06" "d3acdceb56be1bfeaa3e8a25e62d182fa24fefe899d1c17f1dad4c202801000000" "4a493046022100c45af050d3cea806cedd0ab22520c53ebe63b987b8954146cdca" "42487b84bdd6022100b9b027716a6b59e640da50a864d6dd8a0ef24c76ce62391f" "a3eabaf4d2886d2d01ffffffff0200e1f505000000004341046a0765b5865641ce" "08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d484" "8b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00180d8f0000000043" "41046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef1" "70e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0c" "ac000000000100000002e2274e5fea1bf29d963914bd301aa63b64daaf8a3e88f1" "19b5046ca5738a0f6b0000000048473044022016e7a727a061ea2254a6c358376a" "aa617ac537eb836c77d646ebda4c748aac8b0220192ce28bf9f2c06a6467e6531e" "27648d2b3e2e2bae85159c9242939840295ba501ffffffffe2274e5fea1bf29d96" "3914bd301aa63b64daaf8a3e88f119b5046ca5738a0f6b010000004a4930460221" "00b7a1a755588d4190118936e15cd217d133b0e4a53c3c15924010d5648d8925c9" "022100aaef031874db2114f2d869ac2de4ae53908fbfea5b2b1862e181626bb900" "5c9f01ffffffff0200e1f505000000004341044a656f065871a353f216ca26cef8" "dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8d" "d2c875a390f67c1f6c94cfc617c0ea45afac00180d8f000000004341046a0765b5" "865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68ae" "e3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00000000"), SER_NETWORK, PROTOCOL_VERSION); stream >> block; CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL); // Match the first transaction filter.insert(uint256S( "0xe980fe9f792d014e73b95203dc1335c5f9ce19ac537a419e6df5b47aecb93b70")); CMerkleBlock merkleBlock(block, filter); BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash()); BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 1); std::pair pair = merkleBlock.vMatchedTxn[0]; BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256S("0xe980fe9f792d014e73b95203dc1335c5f9ce19ac537a419e6df" "5b47aecb93b70")); BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 0); std::vector vMatched; std::vector vIndex; BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot); BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size()); for (size_t i = 0; i < vMatched.size(); i++) { BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second); } // Match an output from the second transaction (the pubkey for address // 1DZTzaBHUDM7T3QvUKBz4qXMRpkg8jsfB5) // This should match the third transaction because it spends the output // matched // It also matches the fourth transaction, which spends to the pubkey again filter.insert(ParseHex("044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad" "769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875" "a390f67c1f6c94cfc617c0ea45af")); merkleBlock = CMerkleBlock(block, filter); BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash()); BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 4); BOOST_CHECK(pair == merkleBlock.vMatchedTxn[0]); BOOST_CHECK(merkleBlock.vMatchedTxn[1].second == uint256S("0x28204cad1d7fc1d199e8ef4fa22f182de6258a3eaafe1bbe56e" "bdcacd3069a5f")); BOOST_CHECK(merkleBlock.vMatchedTxn[1].first == 1); BOOST_CHECK(merkleBlock.vMatchedTxn[2].second == uint256S("0x6b0f8a73a56c04b519f1883e8aafda643ba61a30bd1439969df" "21bea5f4e27e2")); BOOST_CHECK(merkleBlock.vMatchedTxn[2].first == 2); BOOST_CHECK(merkleBlock.vMatchedTxn[3].second == uint256S("0x3c1d7e82342158e4109df2e0b6348b6e84e403d8b4046d70076" "63ace63cddb23")); BOOST_CHECK(merkleBlock.vMatchedTxn[3].first == 3); BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot); BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size()); for (size_t i = 0; i < vMatched.size(); i++) { BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second); } } BOOST_AUTO_TEST_CASE(merkle_block_2_reversed) { // Like merkle_block_2 except this block gets its transactions reversed in // order to check non-topological processing. // Random real block // (000000005a4ded781e667e06ceefafb71410b511fe0d5adc3e5a27ecbec34ae6) // With 4 txes CBlock block; CDataStream stream( ParseHex( "0100000075616236cc2126035fadb38deb65b9102cc2c41c09cdf29fc051906800" "000000fe7d5e12ef0ff901f6050211249919b1c0653771832b3a80c66cea42847f" "0ae1d4d26e49ffff001d00f0a44104010000000100000000000000000000000000" "00000000000000000000000000000000000000ffffffff0804ffff001d029105ff" "ffffff0100f2052a010000004341046d8709a041d34357697dfcb30a9d05900a62" "94078012bf3bb09c6f9b525f1d16d5503d7905db1ada9501446ea00728668fc571" "9aa80be2fdfc8a858a4dbdd4fbac00000000010000000255605dc6f5c3dc148b6d" "a58442b0b2cd422be385eab2ebea4119ee9c268d28350000000049483045022100" "aa46504baa86df8a33b1192b1b9367b4d729dc41e389f2c04f3e5c7f0559aae702" "205e82253a54bf5c4f65b7428551554b2045167d6d206dfe6a2e198127d3f7df15" "01ffffffff55605dc6f5c3dc148b6da58442b0b2cd422be385eab2ebea4119ee9c" "268d2835010000004847304402202329484c35fa9d6bb32a55a70c0982f606ce0e" "3634b69006138683bcd12cbb6602200c28feb1e2555c3210f1dddb299738b4ff8b" "be9667b68cb8764b5ac17b7adf0001ffffffff0200e1f505000000004341046a07" "65b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a" "68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00180d" "8f000000004341044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad7" "69f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cf" "c617c0ea45afac0000000001000000025f9a06d3acdceb56be1bfeaa3e8a25e62d" "182fa24fefe899d1c17f1dad4c2028000000004847304402205d6058484157235b" "06028c30736c15613a28bdb768ee628094ca8b0030d4d6eb0220328789c9a2ec27" "ddaec0ad5ef58efded42e6ea17c2e1ce838f3d6913f5e95db601ffffffff5f9a06" "d3acdceb56be1bfeaa3e8a25e62d182fa24fefe899d1c17f1dad4c202801000000" "4a493046022100c45af050d3cea806cedd0ab22520c53ebe63b987b8954146cdca" "42487b84bdd6022100b9b027716a6b59e640da50a864d6dd8a0ef24c76ce62391f" "a3eabaf4d2886d2d01ffffffff0200e1f505000000004341046a0765b5865641ce" "08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d484" "8b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00180d8f0000000043" "41046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef1" "70e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0c" "ac000000000100000002e2274e5fea1bf29d963914bd301aa63b64daaf8a3e88f1" "19b5046ca5738a0f6b0000000048473044022016e7a727a061ea2254a6c358376a" "aa617ac537eb836c77d646ebda4c748aac8b0220192ce28bf9f2c06a6467e6531e" "27648d2b3e2e2bae85159c9242939840295ba501ffffffffe2274e5fea1bf29d96" "3914bd301aa63b64daaf8a3e88f119b5046ca5738a0f6b010000004a4930460221" "00b7a1a755588d4190118936e15cd217d133b0e4a53c3c15924010d5648d8925c9" "022100aaef031874db2114f2d869ac2de4ae53908fbfea5b2b1862e181626bb900" "5c9f01ffffffff0200e1f505000000004341044a656f065871a353f216ca26cef8" "dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8d" "d2c875a390f67c1f6c94cfc617c0ea45afac00180d8f000000004341046a0765b5" "865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68ae" "e3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00000000"), SER_NETWORK, PROTOCOL_VERSION); stream >> block; // Reverse the transactions and recalculate merkle root. The remainder of // this test is the same as merkle_block_2 above except the transaction // indices get reversed too. std::reverse(block.vtx.begin(), block.vtx.end()); block.hashMerkleRoot = BlockMerkleRoot(block); CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL); // Match the fourth (was first) transaction filter.insert(uint256S( "0xe980fe9f792d014e73b95203dc1335c5f9ce19ac537a419e6df5b47aecb93b70")); CMerkleBlock merkleBlock(block, filter); BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash()); BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 1); std::pair pair = merkleBlock.vMatchedTxn[0]; BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256S("0xe980fe9f792d014e73b95203dc1335c5f9ce19ac537a419e6df" "5b47aecb93b70")); BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 3); std::vector vMatched; std::vector vIndex; BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot); BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size()); for (size_t i = 0; i < vMatched.size(); i++) { BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second); } // Match an output from the third (was second) transaction (the pubkey for // address 1DZTzaBHUDM7T3QvUKBz4qXMRpkg8jsfB5) This should match the second // (was third) transaction because it spends the output matched // It also matches the first (was fourth) transaction, which spends to the // pubkey again filter.insert(ParseHex("044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad" "769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875" "a390f67c1f6c94cfc617c0ea45af")); merkleBlock = CMerkleBlock(block, filter); BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash()); BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 4); BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256S("0x3c1d7e82342158e4109df2e0b6348b6e84e403d8b4046d70076" "63ace63cddb23")); BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 0); BOOST_CHECK(merkleBlock.vMatchedTxn[1].second == uint256S("0x6b0f8a73a56c04b519f1883e8aafda643ba61a30bd1439969df" "21bea5f4e27e2")); BOOST_CHECK(merkleBlock.vMatchedTxn[1].first == 1); BOOST_CHECK(merkleBlock.vMatchedTxn[2].second == uint256S("0x28204cad1d7fc1d199e8ef4fa22f182de6258a3eaafe1bbe56e" "bdcacd3069a5f")); BOOST_CHECK(merkleBlock.vMatchedTxn[2].first == 2); BOOST_CHECK(pair == merkleBlock.vMatchedTxn[3]); BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot); BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size()); for (size_t i = 0; i < vMatched.size(); i++) { BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second); } } BOOST_AUTO_TEST_CASE(merkle_block_2_with_update_none) { // Random real block // (000000005a4ded781e667e06ceefafb71410b511fe0d5adc3e5a27ecbec34ae6) // With 4 txes CBlock block; CDataStream stream( ParseHex( "0100000075616236cc2126035fadb38deb65b9102cc2c41c09cdf29fc051906800" "000000fe7d5e12ef0ff901f6050211249919b1c0653771832b3a80c66cea42847f" "0ae1d4d26e49ffff001d00f0a44104010000000100000000000000000000000000" "00000000000000000000000000000000000000ffffffff0804ffff001d029105ff" "ffffff0100f2052a010000004341046d8709a041d34357697dfcb30a9d05900a62" "94078012bf3bb09c6f9b525f1d16d5503d7905db1ada9501446ea00728668fc571" "9aa80be2fdfc8a858a4dbdd4fbac00000000010000000255605dc6f5c3dc148b6d" "a58442b0b2cd422be385eab2ebea4119ee9c268d28350000000049483045022100" "aa46504baa86df8a33b1192b1b9367b4d729dc41e389f2c04f3e5c7f0559aae702" "205e82253a54bf5c4f65b7428551554b2045167d6d206dfe6a2e198127d3f7df15" "01ffffffff55605dc6f5c3dc148b6da58442b0b2cd422be385eab2ebea4119ee9c" "268d2835010000004847304402202329484c35fa9d6bb32a55a70c0982f606ce0e" "3634b69006138683bcd12cbb6602200c28feb1e2555c3210f1dddb299738b4ff8b" "be9667b68cb8764b5ac17b7adf0001ffffffff0200e1f505000000004341046a07" "65b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a" "68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00180d" "8f000000004341044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad7" "69f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cf" "c617c0ea45afac0000000001000000025f9a06d3acdceb56be1bfeaa3e8a25e62d" "182fa24fefe899d1c17f1dad4c2028000000004847304402205d6058484157235b" "06028c30736c15613a28bdb768ee628094ca8b0030d4d6eb0220328789c9a2ec27" "ddaec0ad5ef58efded42e6ea17c2e1ce838f3d6913f5e95db601ffffffff5f9a06" "d3acdceb56be1bfeaa3e8a25e62d182fa24fefe899d1c17f1dad4c202801000000" "4a493046022100c45af050d3cea806cedd0ab22520c53ebe63b987b8954146cdca" "42487b84bdd6022100b9b027716a6b59e640da50a864d6dd8a0ef24c76ce62391f" "a3eabaf4d2886d2d01ffffffff0200e1f505000000004341046a0765b5865641ce" "08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d484" "8b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00180d8f0000000043" "41046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef1" "70e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0c" "ac000000000100000002e2274e5fea1bf29d963914bd301aa63b64daaf8a3e88f1" "19b5046ca5738a0f6b0000000048473044022016e7a727a061ea2254a6c358376a" "aa617ac537eb836c77d646ebda4c748aac8b0220192ce28bf9f2c06a6467e6531e" "27648d2b3e2e2bae85159c9242939840295ba501ffffffffe2274e5fea1bf29d96" "3914bd301aa63b64daaf8a3e88f119b5046ca5738a0f6b010000004a4930460221" "00b7a1a755588d4190118936e15cd217d133b0e4a53c3c15924010d5648d8925c9" "022100aaef031874db2114f2d869ac2de4ae53908fbfea5b2b1862e181626bb900" "5c9f01ffffffff0200e1f505000000004341044a656f065871a353f216ca26cef8" "dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8d" "d2c875a390f67c1f6c94cfc617c0ea45afac00180d8f000000004341046a0765b5" "865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68ae" "e3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00000000"), SER_NETWORK, PROTOCOL_VERSION); stream >> block; CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_NONE); // Match the first transaction filter.insert(uint256S( "0xe980fe9f792d014e73b95203dc1335c5f9ce19ac537a419e6df5b47aecb93b70")); CMerkleBlock merkleBlock(block, filter); BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash()); BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 1); std::pair pair = merkleBlock.vMatchedTxn[0]; BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256S("0xe980fe9f792d014e73b95203dc1335c5f9ce19ac537a419e6df" "5b47aecb93b70")); BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 0); std::vector vMatched; std::vector vIndex; BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot); BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size()); for (size_t i = 0; i < vMatched.size(); i++) { BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second); } // Match an output from the second transaction (the pubkey for address // 1DZTzaBHUDM7T3QvUKBz4qXMRpkg8jsfB5) // This should not match the third transaction though it spends the output // matched // It will match the fourth transaction, which has another pay-to-pubkey // output to the same address filter.insert(ParseHex("044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad" "769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875" "a390f67c1f6c94cfc617c0ea45af")); merkleBlock = CMerkleBlock(block, filter); BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash()); BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 3); BOOST_CHECK(pair == merkleBlock.vMatchedTxn[0]); BOOST_CHECK(merkleBlock.vMatchedTxn[1].second == uint256S("0x28204cad1d7fc1d199e8ef4fa22f182de6258a3eaafe1bbe56e" "bdcacd3069a5f")); BOOST_CHECK(merkleBlock.vMatchedTxn[1].first == 1); BOOST_CHECK(merkleBlock.vMatchedTxn[2].second == uint256S("0x3c1d7e82342158e4109df2e0b6348b6e84e403d8b4046d70076" "63ace63cddb23")); BOOST_CHECK(merkleBlock.vMatchedTxn[2].first == 3); BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot); BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size()); for (size_t i = 0; i < vMatched.size(); i++) { BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second); } } BOOST_AUTO_TEST_CASE(merkle_block_3_and_serialize) { // Random real block // (000000000000dab0130bbcc991d3d7ae6b81aa6f50a798888dfe62337458dc45) // With one tx CBlock block; CDataStream stream( ParseHex("0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b00" "00000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3f" "f60abe184f196367291b4d4c86041b8fa45d6301010000000100000000000" "00000000000000000000000000000000000000000000000000000ffffffff" "08044c86041b020a02ffffffff0100f2052a01000000434104ecd3229b057" "1c3be876feaac0442a9f13c5a572742927af1dc623353ecf8c202225f6486" "8137a18cdd85cbbb4c74fbccfd4f49639cf1bdc94a5672bb15ad5d4cac000" "00000"), SER_NETWORK, PROTOCOL_VERSION); stream >> block; CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL); // Match the only transaction filter.insert(uint256S( "0x63194f18be0af63f2c6bc9dc0f777cbefed3d9415c4af83f3ee3a3d669c00cb5")); CMerkleBlock merkleBlock(block, filter); BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash()); BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 1); BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256S("0x63194f18be0af63f2c6bc9dc0f777cbefed3d9415c4af83f3ee" "3a3d669c00cb5")); BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 0); std::vector vMatched; std::vector vIndex; BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot); BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size()); for (size_t i = 0; i < vMatched.size(); i++) { BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second); } CDataStream merkleStream(SER_NETWORK, PROTOCOL_VERSION); merkleStream << merkleBlock; std::vector vch = ParseHex("0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b00" "00000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3f" "f60abe184f196367291b4d4c86041b8fa45d630100000001b50cc069d6a3e" "33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f19630101"); std::vector expected(vch.size()); for (size_t i = 0; i < vch.size(); i++) { expected[i] = (char)vch[i]; } BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), expected.end(), merkleStream.begin(), merkleStream.end()); } BOOST_AUTO_TEST_CASE(merkle_block_4) { // Random real block // (000000000000b731f2eef9e8c63173adfb07e41bd53eb0ef0a6b720d6cb6dea4) // With 7 txes CBlock block; CDataStream stream( ParseHex( "0100000082bb869cf3a793432a66e826e05a6fc37469f8efb7421dc88067010000" "0000007f16c5962e8bd963659c793ce370d95f093bc7e367117b3c30c1f8fdd0d9" "728776381b4d4c86041b554b852907010000000100000000000000000000000000" "00000000000000000000000000000000000000ffffffff07044c86041b0136ffff" "ffff0100f2052a01000000434104eaafc2314def4ca98ac970241bcab022b9c1e1" "f4ea423a20f134c876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad" "1357231a2252247d97a46a91ac000000000100000001bcad20a6a29827d1424f08" "989255120bf7f3e9e3cdaaa6bb31b0737fe048724300000000494830450220356e" "834b046cadc0f8ebb5a8a017b02de59c86305403dad52cd77b55af062ea1022100" "9253cd6c119d4729b77c978e1e2aa19f5ea6e0e52b3f16e32fa608cd5bab753901" "ffffffff02008d380c010000001976a9142b4b8072ecbba129b6453c63e129e643" "207249ca88ac0065cd1d000000001976a9141b8dd13b994bcfc787b32aeadf58cc" "b3615cbd5488ac000000000100000003fdacf9b3eb077412e7a968d2e4f11b9a9d" "ee312d666187ed77ee7d26af16cb0b000000008c493046022100ea1608e70911ca" "0de5af51ba57ad23b9a51db8d28f82c53563c56a05c20f5a87022100a8bdc8b4a8" "acc8634c6b420410150775eb7f2474f5615f7fccd65af30f310fbf01410465fdf4" "9e29b06b9a1582287b6279014f834edc317695d125ef623c1cc3aaece245bd69fc" "ad7508666e9c74a49dc9056d5fc14338ef38118dc4afae5fe2c585caffffffff30" "9e1913634ecb50f3c4f83e96e70b2df071b497b8973a3e75429df397b5af830000" "00004948304502202bdb79c596a9ffc24e96f4386199aba386e9bc7b6071516e2b" "51dda942b3a1ed022100c53a857e76b724fc14d45311eac5019650d415c3abb542" "8f3aae16d8e69bec2301ffffffff2089e33491695080c9edc18a428f7d834db5b6" "d372df13ce2b1b0e0cbcb1e6c10000000049483045022100d4ce67c5896ee251c8" "10ac1ff9ceccd328b497c8f553ab6e08431e7d40bad6b5022033119c0c2b7d792d" "31f1187779c7bd95aefd93d90a715586d73801d9b47471c601ffffffff01007144" "60030000001976a914c7b55141d097ea5df7a0ed330cf794376e53ec8d88ac0000" "000001000000045bf0e214aa4069a3e792ecee1e1bf0c1d397cde8dd08138f4b72" "a00681743447000000008b48304502200c45de8c4f3e2c1821f2fc878cba97b1e6" "f8807d94930713aa1c86a67b9bf1e40221008581abfef2e30f957815fc89978423" "746b2086375ca8ecf359c85c2a5b7c88ad01410462bb73f76ca0994fcb8b4271e6" "fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd62" "38f4d87270efb1d3ae37079b794a92d7ec95ffffffffd669f7d7958d40fc59d225" "3d88e0f248e29b599c80bbcec344a83dda5f9aa72c000000008a47304402207812" "4c8beeaa825f9e0b30bff96e564dd859432f2d0cb3b72d3d5d93d38d7e93022069" "1d233b6c0f995be5acb03d70a7f7a65b6bc9bdd426260f38a1346669507a360141" "0462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab8" "44c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ff" "fffffff878af0d93f5229a68166cf051fd372bb7a537232946e0a46f53636b4daf" "daa4000000008c493046022100c717d1714551663f69c3c5759bdbb3a0fcd3fab0" "23abc0e522fe6440de35d8290221008d9cbe25bffc44af2b18e81c58eb37293fd7" "fe1c2e7b46fc37ee8c96c50ab1e201410462bb73f76ca0994fcb8b4271e6fb7561" "f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d8" "7270efb1d3ae37079b794a92d7ec95ffffffff27f2b668859cd7f2f894aa0fd2d9" "e60963bcd07c88973f425f999b8cbfd7a1e2000000008c493046022100e0084714" "7cbf517bcc2f502f3ddc6d284358d102ed20d47a8aa788a62f0db780022100d17b" "2d6fa84dcaf1c95d88d7e7c30385aecf415588d749afd3ec81f6022cecd7014104" "62bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844" "c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffff" "ffff0100c817a8040000001976a914b6efd80d99179f4f4ff6f4dd0a007d018c38" "5d2188ac000000000100000001834537b2f1ce8ef9373a258e10545ce5a50b758d" "f616cd4356e0032554ebd3c4000000008b483045022100e68f422dd7c34fdce11e" "eb4509ddae38201773dd62f284e8aa9d96f85099d0b002202243bd399ff96b649a" "0fad05fa759d6a882f0af8c90cf7632c2840c29070aec20141045e58067e815c2f" "464c6a2a15f987758374203895710c2d452442e28496ff38ba8f5fd901dc20e29e" "88477167fe4fc299bf818fd0d9e1632d467b2a3d9503b1aaffffffff0280d7e636" "030000001976a914f34c3e10eb387efe872acb614c89e78bfca7815d88ac404b4c" "00000000001976a914a84e272933aaf87e1715d7786c51dfaeb5b65a6f88ac0000" "0000010000000143ac81c8e6f6ef307dfe17f3d906d999e23e0189fda838c5510d" "850927e03ae7000000008c4930460221009c87c344760a64cb8ae6685a3eec2c1a" "c1bed5b88c87de51acd0e124f266c16602210082d07c037359c3a257b5c63ebd90" "f5a5edf97b2ac1c434b08ca998839f346dd40141040ba7e521fa7946d12edbb1d1" "e95a15c34bd4398195e86433c92b431cd315f455fe30032ede69cad9d1e1ed6c3c" "4ec0dbfced53438c625462afb792dcb098544bffffffff0240420f000000000019" "76a9144676d1b820d63ec272f1900d59d43bc6463d96f888ac40420f0000000000" "1976a914648d04341d00d7968b3405c034adc38d4d8fb9bd88ac00000000010000" "000248cc917501ea5c55f4a8d2009c0567c40cfe037c2e71af017d0a452ff705e3" "f1000000008b483045022100bf5fdc86dc5f08a5d5c8e43a8c9d5b1ed8c65562e2" "80007b52b133021acd9acc02205e325d613e555f772802bf413d36ba807892ed1a" "690a77811d3033b3de226e0a01410429fa713b124484cb2bd7b5557b2c0b9df7b2" "b1fee61825eadc5ae6c37a9920d38bfccdc7dc3cb0c47d7b173dbc9db8d37db0a3" "3ae487982c59c6f8606e9d1791ffffffff41ed70551dd7e841883ab8f0b16bf041" "76b7d1480e4f0af9f3d4c3595768d068000000008b4830450221008513ad65187b" "903aed1102d1d0c47688127658c51106753fed0151ce9c16b80902201432b9ebcb" "87bd04ceb2de66035fbbaf4bf8b00d1cfe41f1a1f7338f9ad79d210141049d4cf8" "0125bf50be1709f718c07ad15d0fc612b7da1f5570dddc35f2a352f0f27c978b06" "820edca9ef982c35fda2d255afba340068c5035552368bc7200c1488ffffffff01" "00093d00000000001976a9148edb68822f1ad580b043c7b3df2e400f8699eb4888" "ac00000000"), SER_NETWORK, PROTOCOL_VERSION); stream >> block; CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL); // Match the last transaction filter.insert(uint256S( "0x0a2a92f0bda4727d0a13eaddf4dd9ac6b5c61a1429e6b2b818f19b15df0ac154")); CMerkleBlock merkleBlock(block, filter); BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash()); BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 1); std::pair pair = merkleBlock.vMatchedTxn[0]; BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256S("0x0a2a92f0bda4727d0a13eaddf4dd9ac6b5c61a1429e6b2b818f" "19b15df0ac154")); BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 6); std::vector vMatched; std::vector vIndex; BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot); BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size()); for (size_t i = 0; i < vMatched.size(); i++) { BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second); } // Also match the 4th transaction filter.insert(uint256S( "0x02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041")); merkleBlock = CMerkleBlock(block, filter); BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash()); BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 2); BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256S("0x02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de673" "26471df5bc041")); BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 3); BOOST_CHECK(merkleBlock.vMatchedTxn[1] == pair); BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot); BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size()); for (size_t i = 0; i < vMatched.size(); i++) { BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second); } } BOOST_AUTO_TEST_CASE(merkle_block_4_test_p2pubkey_only) { // Random real block // (000000000000b731f2eef9e8c63173adfb07e41bd53eb0ef0a6b720d6cb6dea4) // With 7 txes CBlock block; CDataStream stream( ParseHex( "0100000082bb869cf3a793432a66e826e05a6fc37469f8efb7421dc88067010000" "0000007f16c5962e8bd963659c793ce370d95f093bc7e367117b3c30c1f8fdd0d9" "728776381b4d4c86041b554b852907010000000100000000000000000000000000" "00000000000000000000000000000000000000ffffffff07044c86041b0136ffff" "ffff0100f2052a01000000434104eaafc2314def4ca98ac970241bcab022b9c1e1" "f4ea423a20f134c876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad" "1357231a2252247d97a46a91ac000000000100000001bcad20a6a29827d1424f08" "989255120bf7f3e9e3cdaaa6bb31b0737fe048724300000000494830450220356e" "834b046cadc0f8ebb5a8a017b02de59c86305403dad52cd77b55af062ea1022100" "9253cd6c119d4729b77c978e1e2aa19f5ea6e0e52b3f16e32fa608cd5bab753901" "ffffffff02008d380c010000001976a9142b4b8072ecbba129b6453c63e129e643" "207249ca88ac0065cd1d000000001976a9141b8dd13b994bcfc787b32aeadf58cc" "b3615cbd5488ac000000000100000003fdacf9b3eb077412e7a968d2e4f11b9a9d" "ee312d666187ed77ee7d26af16cb0b000000008c493046022100ea1608e70911ca" "0de5af51ba57ad23b9a51db8d28f82c53563c56a05c20f5a87022100a8bdc8b4a8" "acc8634c6b420410150775eb7f2474f5615f7fccd65af30f310fbf01410465fdf4" "9e29b06b9a1582287b6279014f834edc317695d125ef623c1cc3aaece245bd69fc" "ad7508666e9c74a49dc9056d5fc14338ef38118dc4afae5fe2c585caffffffff30" "9e1913634ecb50f3c4f83e96e70b2df071b497b8973a3e75429df397b5af830000" "00004948304502202bdb79c596a9ffc24e96f4386199aba386e9bc7b6071516e2b" "51dda942b3a1ed022100c53a857e76b724fc14d45311eac5019650d415c3abb542" "8f3aae16d8e69bec2301ffffffff2089e33491695080c9edc18a428f7d834db5b6" "d372df13ce2b1b0e0cbcb1e6c10000000049483045022100d4ce67c5896ee251c8" "10ac1ff9ceccd328b497c8f553ab6e08431e7d40bad6b5022033119c0c2b7d792d" "31f1187779c7bd95aefd93d90a715586d73801d9b47471c601ffffffff01007144" "60030000001976a914c7b55141d097ea5df7a0ed330cf794376e53ec8d88ac0000" "000001000000045bf0e214aa4069a3e792ecee1e1bf0c1d397cde8dd08138f4b72" "a00681743447000000008b48304502200c45de8c4f3e2c1821f2fc878cba97b1e6" "f8807d94930713aa1c86a67b9bf1e40221008581abfef2e30f957815fc89978423" "746b2086375ca8ecf359c85c2a5b7c88ad01410462bb73f76ca0994fcb8b4271e6" "fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd62" "38f4d87270efb1d3ae37079b794a92d7ec95ffffffffd669f7d7958d40fc59d225" "3d88e0f248e29b599c80bbcec344a83dda5f9aa72c000000008a47304402207812" "4c8beeaa825f9e0b30bff96e564dd859432f2d0cb3b72d3d5d93d38d7e93022069" "1d233b6c0f995be5acb03d70a7f7a65b6bc9bdd426260f38a1346669507a360141" "0462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab8" "44c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ff" "fffffff878af0d93f5229a68166cf051fd372bb7a537232946e0a46f53636b4daf" "daa4000000008c493046022100c717d1714551663f69c3c5759bdbb3a0fcd3fab0" "23abc0e522fe6440de35d8290221008d9cbe25bffc44af2b18e81c58eb37293fd7" "fe1c2e7b46fc37ee8c96c50ab1e201410462bb73f76ca0994fcb8b4271e6fb7561" "f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d8" "7270efb1d3ae37079b794a92d7ec95ffffffff27f2b668859cd7f2f894aa0fd2d9" "e60963bcd07c88973f425f999b8cbfd7a1e2000000008c493046022100e0084714" "7cbf517bcc2f502f3ddc6d284358d102ed20d47a8aa788a62f0db780022100d17b" "2d6fa84dcaf1c95d88d7e7c30385aecf415588d749afd3ec81f6022cecd7014104" "62bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844" "c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffff" "ffff0100c817a8040000001976a914b6efd80d99179f4f4ff6f4dd0a007d018c38" "5d2188ac000000000100000001834537b2f1ce8ef9373a258e10545ce5a50b758d" "f616cd4356e0032554ebd3c4000000008b483045022100e68f422dd7c34fdce11e" "eb4509ddae38201773dd62f284e8aa9d96f85099d0b002202243bd399ff96b649a" "0fad05fa759d6a882f0af8c90cf7632c2840c29070aec20141045e58067e815c2f" "464c6a2a15f987758374203895710c2d452442e28496ff38ba8f5fd901dc20e29e" "88477167fe4fc299bf818fd0d9e1632d467b2a3d9503b1aaffffffff0280d7e636" "030000001976a914f34c3e10eb387efe872acb614c89e78bfca7815d88ac404b4c" "00000000001976a914a84e272933aaf87e1715d7786c51dfaeb5b65a6f88ac0000" "0000010000000143ac81c8e6f6ef307dfe17f3d906d999e23e0189fda838c5510d" "850927e03ae7000000008c4930460221009c87c344760a64cb8ae6685a3eec2c1a" "c1bed5b88c87de51acd0e124f266c16602210082d07c037359c3a257b5c63ebd90" "f5a5edf97b2ac1c434b08ca998839f346dd40141040ba7e521fa7946d12edbb1d1" "e95a15c34bd4398195e86433c92b431cd315f455fe30032ede69cad9d1e1ed6c3c" "4ec0dbfced53438c625462afb792dcb098544bffffffff0240420f000000000019" "76a9144676d1b820d63ec272f1900d59d43bc6463d96f888ac40420f0000000000" "1976a914648d04341d00d7968b3405c034adc38d4d8fb9bd88ac00000000010000" "000248cc917501ea5c55f4a8d2009c0567c40cfe037c2e71af017d0a452ff705e3" "f1000000008b483045022100bf5fdc86dc5f08a5d5c8e43a8c9d5b1ed8c65562e2" "80007b52b133021acd9acc02205e325d613e555f772802bf413d36ba807892ed1a" "690a77811d3033b3de226e0a01410429fa713b124484cb2bd7b5557b2c0b9df7b2" "b1fee61825eadc5ae6c37a9920d38bfccdc7dc3cb0c47d7b173dbc9db8d37db0a3" "3ae487982c59c6f8606e9d1791ffffffff41ed70551dd7e841883ab8f0b16bf041" "76b7d1480e4f0af9f3d4c3595768d068000000008b4830450221008513ad65187b" "903aed1102d1d0c47688127658c51106753fed0151ce9c16b80902201432b9ebcb" "87bd04ceb2de66035fbbaf4bf8b00d1cfe41f1a1f7338f9ad79d210141049d4cf8" "0125bf50be1709f718c07ad15d0fc612b7da1f5570dddc35f2a352f0f27c978b06" "820edca9ef982c35fda2d255afba340068c5035552368bc7200c1488ffffffff01" "00093d00000000001976a9148edb68822f1ad580b043c7b3df2e400f8699eb4888" "ac00000000"), SER_NETWORK, PROTOCOL_VERSION); stream >> block; CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_P2PUBKEY_ONLY); // Match the generation pubkey filter.insert(ParseHex("04eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f" "134c876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce" "13ad1357231a2252247d97a46a91")); // ...and the output address of the 4th transaction filter.insert(ParseHex("b6efd80d99179f4f4ff6f4dd0a007d018c385d21")); CMerkleBlock merkleBlock(block, filter); BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash()); // We should match the generation outpoint const TxId txid1(uint256S( "0x147caa76786596590baa4e98f5d9f48b86c7765e489f7a6ff3360fe5c674360b")); BOOST_CHECK(filter.contains(COutPoint(txid1, 0))); // ... but not the 4th transaction's output (its not pay-2-pubkey) const TxId txid2(uint256S( "0x02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041")); BOOST_CHECK(!filter.contains(COutPoint(txid2, 0))); } BOOST_AUTO_TEST_CASE(merkle_block_4_test_update_none) { // Random real block // (000000000000b731f2eef9e8c63173adfb07e41bd53eb0ef0a6b720d6cb6dea4) // With 7 txes CBlock block; CDataStream stream( ParseHex( "0100000082bb869cf3a793432a66e826e05a6fc37469f8efb7421dc88067010000" "0000007f16c5962e8bd963659c793ce370d95f093bc7e367117b3c30c1f8fdd0d9" "728776381b4d4c86041b554b852907010000000100000000000000000000000000" "00000000000000000000000000000000000000ffffffff07044c86041b0136ffff" "ffff0100f2052a01000000434104eaafc2314def4ca98ac970241bcab022b9c1e1" "f4ea423a20f134c876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad" "1357231a2252247d97a46a91ac000000000100000001bcad20a6a29827d1424f08" "989255120bf7f3e9e3cdaaa6bb31b0737fe048724300000000494830450220356e" "834b046cadc0f8ebb5a8a017b02de59c86305403dad52cd77b55af062ea1022100" "9253cd6c119d4729b77c978e1e2aa19f5ea6e0e52b3f16e32fa608cd5bab753901" "ffffffff02008d380c010000001976a9142b4b8072ecbba129b6453c63e129e643" "207249ca88ac0065cd1d000000001976a9141b8dd13b994bcfc787b32aeadf58cc" "b3615cbd5488ac000000000100000003fdacf9b3eb077412e7a968d2e4f11b9a9d" "ee312d666187ed77ee7d26af16cb0b000000008c493046022100ea1608e70911ca" "0de5af51ba57ad23b9a51db8d28f82c53563c56a05c20f5a87022100a8bdc8b4a8" "acc8634c6b420410150775eb7f2474f5615f7fccd65af30f310fbf01410465fdf4" "9e29b06b9a1582287b6279014f834edc317695d125ef623c1cc3aaece245bd69fc" "ad7508666e9c74a49dc9056d5fc14338ef38118dc4afae5fe2c585caffffffff30" "9e1913634ecb50f3c4f83e96e70b2df071b497b8973a3e75429df397b5af830000" "00004948304502202bdb79c596a9ffc24e96f4386199aba386e9bc7b6071516e2b" "51dda942b3a1ed022100c53a857e76b724fc14d45311eac5019650d415c3abb542" "8f3aae16d8e69bec2301ffffffff2089e33491695080c9edc18a428f7d834db5b6" "d372df13ce2b1b0e0cbcb1e6c10000000049483045022100d4ce67c5896ee251c8" "10ac1ff9ceccd328b497c8f553ab6e08431e7d40bad6b5022033119c0c2b7d792d" "31f1187779c7bd95aefd93d90a715586d73801d9b47471c601ffffffff01007144" "60030000001976a914c7b55141d097ea5df7a0ed330cf794376e53ec8d88ac0000" "000001000000045bf0e214aa4069a3e792ecee1e1bf0c1d397cde8dd08138f4b72" "a00681743447000000008b48304502200c45de8c4f3e2c1821f2fc878cba97b1e6" "f8807d94930713aa1c86a67b9bf1e40221008581abfef2e30f957815fc89978423" "746b2086375ca8ecf359c85c2a5b7c88ad01410462bb73f76ca0994fcb8b4271e6" "fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd62" "38f4d87270efb1d3ae37079b794a92d7ec95ffffffffd669f7d7958d40fc59d225" "3d88e0f248e29b599c80bbcec344a83dda5f9aa72c000000008a47304402207812" "4c8beeaa825f9e0b30bff96e564dd859432f2d0cb3b72d3d5d93d38d7e93022069" "1d233b6c0f995be5acb03d70a7f7a65b6bc9bdd426260f38a1346669507a360141" "0462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab8" "44c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ff" "fffffff878af0d93f5229a68166cf051fd372bb7a537232946e0a46f53636b4daf" "daa4000000008c493046022100c717d1714551663f69c3c5759bdbb3a0fcd3fab0" "23abc0e522fe6440de35d8290221008d9cbe25bffc44af2b18e81c58eb37293fd7" "fe1c2e7b46fc37ee8c96c50ab1e201410462bb73f76ca0994fcb8b4271e6fb7561" "f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d8" "7270efb1d3ae37079b794a92d7ec95ffffffff27f2b668859cd7f2f894aa0fd2d9" "e60963bcd07c88973f425f999b8cbfd7a1e2000000008c493046022100e0084714" "7cbf517bcc2f502f3ddc6d284358d102ed20d47a8aa788a62f0db780022100d17b" "2d6fa84dcaf1c95d88d7e7c30385aecf415588d749afd3ec81f6022cecd7014104" "62bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844" "c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffff" "ffff0100c817a8040000001976a914b6efd80d99179f4f4ff6f4dd0a007d018c38" "5d2188ac000000000100000001834537b2f1ce8ef9373a258e10545ce5a50b758d" "f616cd4356e0032554ebd3c4000000008b483045022100e68f422dd7c34fdce11e" "eb4509ddae38201773dd62f284e8aa9d96f85099d0b002202243bd399ff96b649a" "0fad05fa759d6a882f0af8c90cf7632c2840c29070aec20141045e58067e815c2f" "464c6a2a15f987758374203895710c2d452442e28496ff38ba8f5fd901dc20e29e" "88477167fe4fc299bf818fd0d9e1632d467b2a3d9503b1aaffffffff0280d7e636" "030000001976a914f34c3e10eb387efe872acb614c89e78bfca7815d88ac404b4c" "00000000001976a914a84e272933aaf87e1715d7786c51dfaeb5b65a6f88ac0000" "0000010000000143ac81c8e6f6ef307dfe17f3d906d999e23e0189fda838c5510d" "850927e03ae7000000008c4930460221009c87c344760a64cb8ae6685a3eec2c1a" "c1bed5b88c87de51acd0e124f266c16602210082d07c037359c3a257b5c63ebd90" "f5a5edf97b2ac1c434b08ca998839f346dd40141040ba7e521fa7946d12edbb1d1" "e95a15c34bd4398195e86433c92b431cd315f455fe30032ede69cad9d1e1ed6c3c" "4ec0dbfced53438c625462afb792dcb098544bffffffff0240420f000000000019" "76a9144676d1b820d63ec272f1900d59d43bc6463d96f888ac40420f0000000000" "1976a914648d04341d00d7968b3405c034adc38d4d8fb9bd88ac00000000010000" "000248cc917501ea5c55f4a8d2009c0567c40cfe037c2e71af017d0a452ff705e3" "f1000000008b483045022100bf5fdc86dc5f08a5d5c8e43a8c9d5b1ed8c65562e2" "80007b52b133021acd9acc02205e325d613e555f772802bf413d36ba807892ed1a" "690a77811d3033b3de226e0a01410429fa713b124484cb2bd7b5557b2c0b9df7b2" "b1fee61825eadc5ae6c37a9920d38bfccdc7dc3cb0c47d7b173dbc9db8d37db0a3" "3ae487982c59c6f8606e9d1791ffffffff41ed70551dd7e841883ab8f0b16bf041" "76b7d1480e4f0af9f3d4c3595768d068000000008b4830450221008513ad65187b" "903aed1102d1d0c47688127658c51106753fed0151ce9c16b80902201432b9ebcb" "87bd04ceb2de66035fbbaf4bf8b00d1cfe41f1a1f7338f9ad79d210141049d4cf8" "0125bf50be1709f718c07ad15d0fc612b7da1f5570dddc35f2a352f0f27c978b06" "820edca9ef982c35fda2d255afba340068c5035552368bc7200c1488ffffffff01" "00093d00000000001976a9148edb68822f1ad580b043c7b3df2e400f8699eb4888" "ac00000000"), SER_NETWORK, PROTOCOL_VERSION); stream >> block; CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_NONE); // Match the generation pubkey filter.insert(ParseHex("04eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f" "134c876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce" "13ad1357231a2252247d97a46a91")); // ...and the output address of the 4th transaction filter.insert(ParseHex("b6efd80d99179f4f4ff6f4dd0a007d018c385d21")); CMerkleBlock merkleBlock(block, filter); BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash()); // We shouldn't match any outpoints (UPDATE_NONE) const TxId txid1(uint256S( "0x147caa76786596590baa4e98f5d9f48b86c7765e489f7a6ff3360fe5c674360b")); BOOST_CHECK(!filter.contains(COutPoint(txid1, 0))); const TxId txid2(uint256S( "0x02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041")); BOOST_CHECK(!filter.contains(COutPoint(txid2, 0))); } static std::vector RandomData() { uint256 r = InsecureRand256(); return std::vector(r.begin(), r.end()); } 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); // Overfill: static const int DATASIZE = 399; std::vector data[DATASIZE]; for (int i = 0; i < DATASIZE; i++) { data[i] = RandomData(); rb1.insert(data[i]); } // Last 100 guaranteed to be remembered: for (int i = 299; i < DATASIZE; i++) { BOOST_CHECK(rb1.contains(data[i])); } // false positive rate is 1%, so we should get about 100 hits if // testing 10,000 random keys. We get worst-case false positive // behavior when the filter is as full as possible, which is // when we've inserted one minus an integer multiple of nElement*2. unsigned int nHits = 0; for (int i = 0; i < 10000; i++) { if (rb1.contains(RandomData())) { ++nHits; } } // Expect about 100 hits BOOST_CHECK_EQUAL(nHits, 75); BOOST_CHECK(rb1.contains(data[DATASIZE - 1])); rb1.reset(); BOOST_CHECK(!rb1.contains(data[DATASIZE - 1])); // Now roll through data, make sure last 100 entries // are always remembered: for (int i = 0; i < DATASIZE; i++) { if (i >= 100) { BOOST_CHECK(rb1.contains(data[i - 100])); } rb1.insert(data[i]); BOOST_CHECK(rb1.contains(data[i])); } // Insert 999 more random entries: for (int i = 0; i < 999; i++) { std::vector d = RandomData(); rb1.insert(d); BOOST_CHECK(rb1.contains(d)); } // Sanity check to make sure the filter isn't just filling up: nHits = 0; for (int i = 0; i < DATASIZE; i++) { if (rb1.contains(data[i])) { ++nHits; } } // Expect about 5 false positives BOOST_CHECK_EQUAL(nHits, 6); // last-1000-entry, 0.01% false positive: CRollingBloomFilter rb2(1000, 0.001); for (int i = 0; i < DATASIZE; i++) { rb2.insert(data[i]); } // ... room for all of them: 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 7db6c5074..9b09b6541 100644 --- a/src/test/bswap_tests.cpp +++ b/src/test/bswap_tests.cpp @@ -1,26 +1,26 @@ -// Copyright (c) 2016 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 #include #include BOOST_FIXTURE_TEST_SUITE(bswap_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(bswap_tests) { // Sibling in bitcoin/src/qt/test/compattests.cpp uint16_t u1 = 0x1234; uint32_t u2 = 0x56789abc; uint64_t u3 = 0xdef0123456789abc; uint16_t e1 = 0x3412; uint32_t e2 = 0xbc9a7856; uint64_t e3 = 0xbc9a78563412f0de; BOOST_CHECK(bswap_16(u1) == e1); BOOST_CHECK(bswap_32(u2) == e2); BOOST_CHECK(bswap_64(u3) == e3); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp index 7660a906e..d5599bd84 100644 --- a/src/test/checkqueue_tests.cpp +++ b/src/test/checkqueue_tests.cpp @@ -1,417 +1,417 @@ -// Copyright (c) 2012-2018 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 #include #include #include #include #include #include #include #include #include #include #include #include #include // BasicTestingSetup not sufficient because nScriptCheckThreads is not set // otherwise. BOOST_FIXTURE_TEST_SUITE(checkqueue_tests, TestingSetup) static const unsigned int QUEUE_BATCH_SIZE = 128; struct FakeCheck { bool operator()() { return true; } void swap(FakeCheck &x){}; }; struct FakeCheckCheckCompletion { static std::atomic n_calls; bool operator()() { n_calls.fetch_add(1, std::memory_order_relaxed); return true; } void swap(FakeCheckCheckCompletion &x){}; }; struct FailingCheck { bool fails; FailingCheck(bool _fails) : fails(_fails){}; FailingCheck() : fails(true){}; bool operator()() { return !fails; } void swap(FailingCheck &x) { std::swap(fails, x.fails); }; }; struct UniqueCheck { static std::mutex m; static std::unordered_multiset results; size_t check_id; UniqueCheck(size_t check_id_in) : check_id(check_id_in){}; UniqueCheck() : check_id(0){}; bool operator()() { std::lock_guard l(m); results.insert(check_id); return true; } void swap(UniqueCheck &x) { std::swap(x.check_id, check_id); }; }; struct MemoryCheck { static std::atomic fake_allocated_memory; bool b{false}; bool operator()() { return true; } MemoryCheck(){}; MemoryCheck(const MemoryCheck &x) { // We have to do this to make sure that destructor calls are paired // // Really, copy constructor should be deletable, but CCheckQueue breaks // if it is deleted because of internal push_back. fake_allocated_memory.fetch_add(b, std::memory_order_relaxed); }; MemoryCheck(bool b_) : b(b_) { fake_allocated_memory.fetch_add(b, std::memory_order_relaxed); }; ~MemoryCheck() { fake_allocated_memory.fetch_sub(b, std::memory_order_relaxed); }; void swap(MemoryCheck &x) { std::swap(b, x.b); }; }; struct FrozenCleanupCheck { static std::atomic nFrozen; static std::condition_variable cv; static std::mutex m; // Freezing can't be the default initialized behavior given how the queue // swaps in default initialized Checks. bool should_freeze{false}; bool operator()() { return true; } FrozenCleanupCheck() {} ~FrozenCleanupCheck() { if (should_freeze) { std::unique_lock l(m); nFrozen.store(1, std::memory_order_relaxed); cv.notify_one(); cv.wait( l, [] { return nFrozen.load(std::memory_order_relaxed) == 0; }); } } void swap(FrozenCleanupCheck &x) { std::swap(should_freeze, x.should_freeze); }; }; // Static Allocations std::mutex FrozenCleanupCheck::m{}; std::atomic FrozenCleanupCheck::nFrozen{0}; std::condition_variable FrozenCleanupCheck::cv{}; std::mutex UniqueCheck::m; std::unordered_multiset UniqueCheck::results; std::atomic FakeCheckCheckCompletion::n_calls{0}; std::atomic MemoryCheck::fake_allocated_memory{0}; // Queue Typedefs typedef CCheckQueue Correct_Queue; typedef CCheckQueue Standard_Queue; typedef CCheckQueue Failing_Queue; typedef CCheckQueue Unique_Queue; typedef CCheckQueue Memory_Queue; typedef CCheckQueue FrozenCleanup_Queue; /** This test case checks that the CCheckQueue works properly * with each specified size_t Checks pushed. */ static void Correct_Queue_range(std::vector range) { auto small_queue = std::make_unique(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 vChecks; for (const size_t i : range) { size_t total = i; FakeCheckCheckCompletion::n_calls = 0; CCheckQueueControl control(small_queue.get()); while (total) { vChecks.resize(std::min(total, (size_t)InsecureRandRange(10))); total -= vChecks.size(); control.Add(vChecks); } BOOST_REQUIRE(control.Wait()); if (FakeCheckCheckCompletion::n_calls != i) { BOOST_REQUIRE_EQUAL(FakeCheckCheckCompletion::n_calls, i); } } tg.interrupt_all(); tg.join_all(); } /** Test that 0 checks is correct */ BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_Zero) { std::vector range; range.push_back((size_t)0); Correct_Queue_range(range); } /** Test that 1 check is correct */ BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_One) { std::vector range; range.push_back((size_t)1); Correct_Queue_range(range); } /** Test that MAX check is correct */ BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_Max) { std::vector range; range.push_back(100000); Correct_Queue_range(range); } /** Test that random numbers of checks are correct */ BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_Random) { std::vector range; range.reserve(100000 / 1000); for (size_t i = 2; i < 100000; i += std::max((size_t)1, (size_t)InsecureRandRange(std::min( (size_t)1000, ((size_t)100000) - i)))) { range.push_back(i); } Correct_Queue_range(range); } /** Test that failing checks are caught */ BOOST_AUTO_TEST_CASE(test_CheckQueue_Catches_Failure) { auto fail_queue = std::make_unique(QUEUE_BATCH_SIZE); boost::thread_group tg; for (auto x = 0; x < nScriptCheckThreads; ++x) { tg.create_thread([&] { fail_queue->Thread(); }); } for (size_t i = 0; i < 1001; ++i) { CCheckQueueControl control(fail_queue.get()); size_t remaining = i; while (remaining) { size_t r = InsecureRandRange(10); std::vector vChecks; vChecks.reserve(r); for (size_t k = 0; k < r && remaining; k++, remaining--) { vChecks.emplace_back(remaining == 1); } control.Add(vChecks); } bool success = control.Wait(); if (i > 0) { BOOST_REQUIRE(!success); } else if (i == 0) { BOOST_REQUIRE(success); } } tg.interrupt_all(); tg.join_all(); } // Test that a block validation which fails does not interfere with // future blocks, ie, the bad state is cleared. BOOST_AUTO_TEST_CASE(test_CheckQueue_Recovers_From_Failure) { auto fail_queue = std::make_unique(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 (const bool end_fails : {true, false}) { CCheckQueueControl control(fail_queue.get()); { std::vector vChecks; vChecks.resize(100, false); vChecks[99] = end_fails; control.Add(vChecks); } bool r = control.Wait(); BOOST_REQUIRE(r != end_fails); } } tg.interrupt_all(); tg.join_all(); } // Test that unique checks are actually all called individually, rather than // just one check being called repeatedly. Test that checks are not called // more than once as well BOOST_AUTO_TEST_CASE(test_CheckQueue_UniqueCheck) { auto queue = std::make_unique(QUEUE_BATCH_SIZE); boost::thread_group tg; for (auto x = 0; x < nScriptCheckThreads; ++x) { tg.create_thread([&] { queue->Thread(); }); } size_t COUNT = 100000; size_t total = COUNT; { CCheckQueueControl control(queue.get()); while (total) { size_t r = InsecureRandRange(10); std::vector vChecks; for (size_t k = 0; k < r && total; k++) { vChecks.emplace_back(--total); } control.Add(vChecks); } } bool r = true; BOOST_REQUIRE_EQUAL(UniqueCheck::results.size(), COUNT); for (size_t i = 0; i < COUNT; ++i) { r = r && UniqueCheck::results.count(i) == 1; } BOOST_REQUIRE(r); tg.interrupt_all(); tg.join_all(); } // Test that blocks which might allocate lots of memory free their memory // aggressively. // // This test attempts to catch a pathological case where by lazily freeing // checks might mean leaving a check un-swapped out, and decreasing by 1 each // time could leave the data hanging across a sequence of blocks. BOOST_AUTO_TEST_CASE(test_CheckQueue_Memory) { auto queue = std::make_unique(QUEUE_BATCH_SIZE); boost::thread_group tg; for (auto x = 0; x < nScriptCheckThreads; ++x) { tg.create_thread([&] { queue->Thread(); }); } for (size_t i = 0; i < 1000; ++i) { size_t total = i; { CCheckQueueControl control(queue.get()); while (total) { size_t r = InsecureRandRange(10); std::vector vChecks; for (size_t k = 0; k < r && total; k++) { total--; // Each iteration leaves data at the front, back, and middle // to catch any sort of deallocation failure vChecks.emplace_back(total == 0 || total == i || total == i / 2); } control.Add(vChecks); } } BOOST_REQUIRE_EQUAL(MemoryCheck::fake_allocated_memory, 0U); } tg.interrupt_all(); tg.join_all(); } // Test that a new verification cannot occur until all checks // have been destructed BOOST_AUTO_TEST_CASE(test_CheckQueue_FrozenCleanup) { auto queue = std::make_unique(QUEUE_BATCH_SIZE); boost::thread_group tg; bool fails = false; for (auto x = 0; x < nScriptCheckThreads; ++x) { tg.create_thread([&] { queue->Thread(); }); } std::thread t0([&]() { CCheckQueueControl control(queue.get()); std::vector vChecks(1); // Freezing can't be the default initialized behavior given how the // queue // swaps in default initialized Checks (otherwise freezing destructor // would get called twice). vChecks[0].should_freeze = true; control.Add(vChecks); control.Wait(); // Hangs here }); { std::unique_lock l(FrozenCleanupCheck::m); // Wait until the queue has finished all jobs and frozen FrozenCleanupCheck::cv.wait( l, []() { return FrozenCleanupCheck::nFrozen == 1; }); } // Try to get control of the queue a bunch of times for (auto x = 0; x < 100 && !fails; ++x) { fails = queue->ControlMutex.try_lock(); } { // Unfreeze (we need lock n case of spurious wakeup) std::unique_lock l(FrozenCleanupCheck::m); FrozenCleanupCheck::nFrozen = 0; } // Awaken frozen destructor FrozenCleanupCheck::cv.notify_one(); // Wait for control to finish t0.join(); tg.interrupt_all(); tg.join_all(); BOOST_REQUIRE(!fails); } /** Test that CCheckQueueControl is threadsafe */ BOOST_AUTO_TEST_CASE(test_CheckQueueControl_Locks) { auto queue = std::make_unique(QUEUE_BATCH_SIZE); { boost::thread_group tg; std::atomic nThreads{0}; std::atomic fails{0}; for (size_t i = 0; i < 3; ++i) { tg.create_thread([&] { CCheckQueueControl control(queue.get()); // While sleeping, no other thread should execute to this point auto observed = ++nThreads; MilliSleep(10); fails += observed != nThreads; }); } tg.join_all(); BOOST_REQUIRE_EQUAL(fails, 0); } { boost::thread_group tg; std::mutex m; std::condition_variable cv; bool has_lock{false}; bool has_tried{false}; bool done{false}; bool done_ack{false}; { std::unique_lock l(m); tg.create_thread([&] { CCheckQueueControl control(queue.get()); std::unique_lock ll(m); has_lock = true; cv.notify_one(); cv.wait(ll, [&] { return has_tried; }); done = true; cv.notify_one(); // Wait until the done is acknowledged // cv.wait(ll, [&] { return done_ack; }); }); // Wait for thread to get the lock cv.wait(l, [&]() { return has_lock; }); bool fails = false; for (auto x = 0; x < 100 && !fails; ++x) { fails = queue->ControlMutex.try_lock(); } has_tried = true; cv.notify_one(); cv.wait(l, [&]() { return done; }); // Acknowledge the done done_ack = true; cv.notify_one(); BOOST_REQUIRE(!fails); } tg.join_all(); } } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 8979dbafa..177f82ceb 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -1,912 +1,912 @@ -// Copyright (c) 2014-2016 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 #include #include #include