full patch for 13aa0b860e9692715d96b13acacb3f83a537b905
<details>
<summary>Details</summary>
diff --git a/src/arith_uint256.h b/src/arith_uint256.h
index e021947381..b07e8e9f41 100644
--- a/src/arith_uint256.h
+++ b/src/arith_uint256.h
@@ -31,7 +31,7 @@ protected:
uint32_t pn[WIDTH];
public:
- constexpr base_uint()
+ explicit constexpr base_uint()
{
for (int i = 0; i < WIDTH; i++)
pn[i] = 0;
@@ -243,8 +243,8 @@ class arith_uint256 : public base_uint<256>
{
public:
constexpr arith_uint256() = default;
- constexpr arith_uint256(const base_uint<256>& b) : base_uint<256>(b) {}
- constexpr arith_uint256(uint64_t b) : base_uint<256>(b) {}
+ constexpr arith_uint256(const base_uint& b) : base_uint(b) {}
+ constexpr arith_uint256(const uint64_t b) : base_uint(b) {}
/**
* The "compact" format is a representation of a whole
diff --git a/src/test/headers_sync_chainwork_tests.cpp b/src/test/headers_sync_chainwork_tests.cpp
index b696285d0e..264959f8c3 100644
--- a/src/test/headers_sync_chainwork_tests.cpp
+++ b/src/test/headers_sync_chainwork_tests.cpp
@@ -13,32 +13,35 @@
#include <boost/test/unit_test.hpp>
-constexpr int TARGET_BLOCKS{15000};
+constexpr size_t TARGET_BLOCKS{15'000};
constexpr arith_uint256 CHAIN_WORK{TARGET_BLOCKS * 2};
-struct HeadersGeneratorSetup : public RegTestingSetup {
+struct HeadersGeneratorSetup : RegTestingSetup
+{
/** Search for a nonce to meet (regtest) proof of work */
- void FindProofOfWork(CBlockHeader& starting_header);
+ static void FindProofOfWork(CBlockHeader& starting_header);
/**
* Generate headers in a chain that build off a given starting hash, using
* the given nVersion, advancing time by 1 second from the starting
* prev_time, and with a fixed merkle root hash.
*/
- void GenerateHeaders(std::vector<CBlockHeader>& headers, size_t count,
- const uint256& starting_hash, const int nVersion, int prev_time,
- const uint256& merkle_root, const uint32_t nBits);
+ static void GenerateHeaders(
+ std::vector<CBlockHeader>& headers, size_t count,
+ const uint256& starting_hash, int nVersion, int prev_time,
+ const uint256& merkle_root, uint32_t nBits);
};
void HeadersGeneratorSetup::FindProofOfWork(CBlockHeader& starting_header)
{
while (!CheckProofOfWork(starting_header.GetHash(), starting_header.nBits, Params().GetConsensus())) {
- ++(starting_header.nNonce);
+ ++starting_header.nNonce;
}
}
-void HeadersGeneratorSetup::GenerateHeaders(std::vector<CBlockHeader>& headers,
- size_t count, const uint256& starting_hash, const int nVersion, int prev_time,
- const uint256& merkle_root, const uint32_t nBits)
+void HeadersGeneratorSetup::GenerateHeaders(
+ std::vector<CBlockHeader>& headers,
+ const size_t count, const uint256& starting_hash, const int nVersion, int prev_time,
+ const uint256& merkle_root, const uint32_t nBits)
{
uint256 prev_hash = starting_hash;
@@ -48,7 +51,7 @@ void HeadersGeneratorSetup::GenerateHeaders(std::vector<CBlockHeader>& headers,
next_header.nVersion = nVersion;
next_header.hashPrevBlock = prev_hash;
next_header.hashMerkleRoot = merkle_root;
- next_header.nTime = prev_time+1;
+ next_header.nTime = prev_time + 1;
next_header.nBits = nBits;
FindProofOfWork(next_header);
@@ -65,13 +68,20 @@ BOOST_FIXTURE_TEST_SUITE(headers_sync_chainwork_tests, HeadersGeneratorSetup)
// updates to the REDOWNLOAD phase successfully.
// 2. Then we deliver the second set of headers and verify that they fail
// processing (presumably due to commitments not matching).
-static void SneakyRedownload(const std::vector<CBlockHeader>& first_chain, const std::vector<CBlockHeader>& second_chain, const CBlockIndex* chain_start);
+static void SneakyRedownload(
+ const std::span<const CBlockHeader> first_chain,
+ const std::span<const CBlockHeader> second_chain,
+ const CBlockIndex* chain_start);
// 3. Verify that repeating with the first set of headers in both phases is
// successful.
-static void HappyPath(const std::vector<CBlockHeader>& first_chain, const CBlockIndex* chain_start);
+static void HappyPath(
+ const std::span<const CBlockHeader> first_chain,
+ const CBlockIndex* chain_start);
// 4. Finally, repeat the second set of headers in both phases to demonstrate
// behavior when the chain a peer provides has too little work.
-static void TooLittleWork(const std::vector<CBlockHeader>& second_chain, const CBlockIndex* chain_start);
+static void TooLittleWork(
+ const std::span<const CBlockHeader> second_chain,
+ const CBlockIndex* chain_start);
BOOST_AUTO_TEST_CASE(headers_sync_state)
{
@@ -94,81 +104,101 @@ BOOST_AUTO_TEST_CASE(headers_sync_state)
TooLittleWork(second_chain, chain_start);
}
-static void SneakyRedownload(const std::vector<CBlockHeader>& first_chain, const std::vector<CBlockHeader>& second_chain, const CBlockIndex* chain_start)
+static void SneakyRedownload(
+ const std::span<const CBlockHeader> first_chain,
+ const std::span<const CBlockHeader> second_chain,
+ const CBlockIndex* chain_start)
{
// Feed the first chain to HeadersSyncState, by delivering 1 header
// initially and then the rest.
HeadersSyncState hss{0, Params().GetConsensus(), chain_start, CHAIN_WORK};
- auto result{hss.ProcessNextHeaders(std::span{first_chain.begin(), 1}, true)};
- BOOST_REQUIRE_EQUAL(hss.GetState(), HeadersSyncState::State::PRESYNC);
- BOOST_CHECK(result.success);
- BOOST_CHECK(result.request_more);
- BOOST_CHECK_EQUAL(result.pow_validated_headers.size(), 0);
- BOOST_CHECK_EQUAL(hss.NextHeadersRequestLocator().vHave.front(), first_chain.front().GetHash());
+ {
+ const auto [pow_validated_headers, success, request_more]{hss.ProcessNextHeaders({first_chain.begin(), 1}, true)};
+ BOOST_REQUIRE_EQUAL(hss.GetState(), HeadersSyncState::State::PRESYNC);
+ BOOST_CHECK(success);
+ BOOST_CHECK(request_more);
+ BOOST_CHECK_EQUAL(pow_validated_headers.size(), 0);
+ BOOST_CHECK_EQUAL(hss.NextHeadersRequestLocator().vHave.front(), first_chain.front().GetHash());
+ }
// Pretend the first header is still "full", so we don't abort.
- result = hss.ProcessNextHeaders(std::span{first_chain.begin() + 1, first_chain.end()}, true);
- // This chain should look valid, and we should have met the proof-of-work
- // requirement during PRESYNC and transitioned to REDOWNLOAD.
- BOOST_REQUIRE_EQUAL(hss.GetState(), HeadersSyncState::State::REDOWNLOAD);
- BOOST_CHECK(result.success);
- BOOST_CHECK(result.request_more);
- BOOST_CHECK_EQUAL(result.pow_validated_headers.size(), 0);
- // The locator should reset to genesis.
- BOOST_CHECK_EQUAL(hss.NextHeadersRequestLocator().vHave.front(), Params().GenesisBlock().GetHash());
+ {
+ const auto [pow_validated_headers, success, request_more]{hss.ProcessNextHeaders({first_chain.begin() + 1, first_chain.end()}, true)};
+ // This chain should look valid, and we should have met the proof-of-work
+ // requirement during PRESYNC and transitioned to REDOWNLOAD.
+ BOOST_REQUIRE_EQUAL(hss.GetState(), HeadersSyncState::State::REDOWNLOAD);
+ BOOST_CHECK(success);
+ BOOST_CHECK(request_more);
+ BOOST_CHECK_EQUAL(pow_validated_headers.size(), 0);
+ // The locator should reset to genesis.
+ BOOST_CHECK_EQUAL(hss.NextHeadersRequestLocator().vHave.front(), Params().GenesisBlock().GetHash());
+ }
// Try to sneakily feed back the second chain during REDOWNLOAD.
- result = hss.ProcessNextHeaders(second_chain, true);
- BOOST_REQUIRE_EQUAL(hss.GetState(), HeadersSyncState::State::FINAL);
- BOOST_CHECK(!result.success); // foiled!
- BOOST_CHECK_EQUAL(result.pow_validated_headers.size(), 0);
+ {
+ const auto [pow_validated_headers, success, request_more]{hss.ProcessNextHeaders(second_chain, true)};
+ BOOST_REQUIRE_EQUAL(hss.GetState(), HeadersSyncState::State::FINAL);
+ BOOST_CHECK(!success); // foiled!
+ BOOST_CHECK(!request_more);
+ BOOST_CHECK_EQUAL(pow_validated_headers.size(), 0);
+ }
}
-static void HappyPath(const std::vector<CBlockHeader>& first_chain, const CBlockIndex* chain_start)
+static void HappyPath(
+ const std::span<const CBlockHeader> first_chain,
+ const CBlockIndex* chain_start)
{
// This time we feed the first chain twice.
HeadersSyncState hss{0, Params().GetConsensus(), chain_start, CHAIN_WORK};
- auto result{hss.ProcessNextHeaders(first_chain, true)};
- // Switched from PRESYNC to REDOWNLOAD after reaching sufficient work:
- BOOST_REQUIRE_EQUAL(hss.GetState(), HeadersSyncState::State::REDOWNLOAD);
- BOOST_CHECK(result.success);
- BOOST_CHECK(result.request_more);
- BOOST_CHECK_EQUAL(result.pow_validated_headers.size(), 0);
- // The locator should reset to genesis.
- BOOST_CHECK_EQUAL(hss.NextHeadersRequestLocator().vHave.front(), Params().GenesisBlock().GetHash());
-
- result = hss.ProcessNextHeaders(first_chain, true);
- // Nothing left for the sync logic to do:
- BOOST_REQUIRE_EQUAL(hss.GetState(), HeadersSyncState::State::FINAL);
- BOOST_CHECK(result.success);
- BOOST_CHECK(!result.request_more);
- // All headers should be ready for acceptance:
- BOOST_CHECK_EQUAL(result.pow_validated_headers.size(), first_chain.size());
+ {
+ const auto [pow_validated_headers, success, request_more]{hss.ProcessNextHeaders(first_chain, true)};
+ // Switched from PRESYNC to REDOWNLOAD after reaching sufficient work:
+ BOOST_REQUIRE_EQUAL(hss.GetState(), HeadersSyncState::State::REDOWNLOAD);
+ BOOST_CHECK(success);
+ BOOST_CHECK(request_more);
+ BOOST_CHECK_EQUAL(pow_validated_headers.size(), 0);
+ // The locator should reset to genesis.
+ BOOST_CHECK_EQUAL(hss.NextHeadersRequestLocator().vHave.front(), Params().GenesisBlock().GetHash());
+ }
+
+ {
+ const auto [pow_validated_headers, success, request_more]{hss.ProcessNextHeaders(first_chain, true)};
+ // Nothing left for the sync logic to do:
+ BOOST_REQUIRE_EQUAL(hss.GetState(), HeadersSyncState::State::FINAL);
+ BOOST_CHECK(success);
+ BOOST_CHECK(!request_more);
+ // All headers should be ready for acceptance:
+ BOOST_CHECK_EQUAL(pow_validated_headers.size(), first_chain.size());
+ }
}
-static void TooLittleWork(const std::vector<CBlockHeader>& second_chain, const CBlockIndex* chain_start)
+static void TooLittleWork(
+ const std::span<const CBlockHeader> second_chain,
+ const CBlockIndex* chain_start)
{
- // Verify that just trying to process the second chain would not succeed
- // (too little work).
+ // Verify that just trying to process the second chain would not succeed (too little work).
HeadersSyncState hss{0, Params().GetConsensus(), chain_start, CHAIN_WORK};
BOOST_REQUIRE_EQUAL(hss.GetState(), HeadersSyncState::State::PRESYNC);
// Pretend just the first message is "full", so we don't abort.
- auto result{hss.ProcessNextHeaders(std::span{second_chain.begin(), 1}, true)};
- BOOST_REQUIRE_EQUAL(hss.GetState(), HeadersSyncState::State::PRESYNC);
- BOOST_CHECK(result.success);
- BOOST_CHECK(result.request_more);
- BOOST_CHECK_EQUAL(result.pow_validated_headers.size(), 0);
+ {
+ const auto [pow_validated_headers, success, request_more]{hss.ProcessNextHeaders({second_chain.begin(), 1}, true)};
+ BOOST_REQUIRE_EQUAL(hss.GetState(), HeadersSyncState::State::PRESYNC);
+ BOOST_CHECK(success);
+ BOOST_CHECK(request_more);
+ BOOST_CHECK_EQUAL(pow_validated_headers.size(), 0);
+ }
// Tell the sync logic that the headers message was not full, implying no
// more headers can be requested. For a low-work-chain, this should cause
// the sync to end with no headers for acceptance.
- result = hss.ProcessNextHeaders(std::span{second_chain.begin() + 1, second_chain.end()}, false);
- BOOST_REQUIRE_EQUAL(hss.GetState(), HeadersSyncState::State::FINAL);
- BOOST_CHECK(!result.request_more);
- BOOST_CHECK_EQUAL(result.pow_validated_headers.size(), 0);
- // Nevertheless, no validation errors should have been detected with the
- // chain:
- BOOST_CHECK(result.success);
+ {
+ const auto [pow_validated_headers, success, request_more]{hss.ProcessNextHeaders({second_chain.begin() + 1, second_chain.end()}, false)};
+ BOOST_REQUIRE_EQUAL(hss.GetState(), HeadersSyncState::State::FINAL);
+ BOOST_CHECK(!request_more);
+ BOOST_CHECK_EQUAL(pow_validated_headers.size(), 0);
+ // Nevertheless, no validation errors should have been detected with the chain:
+ BOOST_CHECK(success);
+ }
}
BOOST_AUTO_TEST_SUITE_END()
</details>