1010#include < test/util/net.h>
1111#include < test/util/script.h>
1212#include < test/util/setup_common.h>
13+ #include < uint256.h>
1314#include < validation.h>
1415
1516namespace {
@@ -20,9 +21,7 @@ class HeadersSyncSetup : public TestingSetup
2021 std::vector<CNode*> m_connections;
2122
2223public:
23- HeadersSyncSetup (const ChainType chain_type = ChainType::MAIN,
24- TestOpts opts = {})
25- : TestingSetup(chain_type, opts)
24+ HeadersSyncSetup (const ChainType chain_type, TestOpts opts) : TestingSetup(chain_type, opts)
2625 {
2726 PeerManager::Options peerman_opts;
2827 node::ApplyArgsManOptions (*m_node.args , peerman_opts);
@@ -116,9 +115,9 @@ CBlock ConsumeBlock(FuzzedDataProvider& fuzzed_data_provider, const uint256& pre
116115 return block;
117116}
118117
119- void FinalizeHeader (CBlockHeader& header)
118+ void FinalizeHeader (CBlockHeader& header, const ChainstateManager& chainman )
120119{
121- while (!CheckProofOfWork (header.GetHash (), header.nBits , Params ().GetConsensus ())) {
120+ while (!CheckProofOfWork (header.GetHash (), header.nBits , chainman. GetParams ().GetConsensus ())) {
122121 ++(header.nNonce );
123122 }
124123}
@@ -144,17 +143,20 @@ FUZZ_TARGET(p2p_headers_presync, .init = initialize)
144143
145144 FuzzedDataProvider fuzzed_data_provider{buffer.data (), buffer.size ()};
146145
147- CBlockHeader base{Params ().GenesisBlock ()};
146+ CBlockHeader base{chainman. GetParams ().GenesisBlock ()};
148147 SetMockTime (base.nTime );
149148
150149 // The chain is just a single block, so this is equal to 1
151150 size_t original_index_size{WITH_LOCK (cs_main, return chainman.m_blockman .m_block_index .size ())};
151+ arith_uint256 total_work{WITH_LOCK (cs_main, return chainman.m_best_header ->nChainWork )};
152+
153+ std::vector<CBlockHeader> all_headers;
152154
153155 LIMITED_WHILE (fuzzed_data_provider.ConsumeBool (), 100 )
154156 {
155157 auto finalized_block = [&]() {
156158 CBlock block = ConsumeBlock (fuzzed_data_provider, base.GetHash (), base.nBits );
157- FinalizeHeader (block);
159+ FinalizeHeader (block, chainman );
158160 return block;
159161 };
160162
@@ -167,10 +169,12 @@ FUZZ_TARGET(p2p_headers_presync, .init = initialize)
167169 headers.resize (FUZZ_MAX_HEADERS_RESULTS);
168170 for (CBlock& header : headers) {
169171 header = ConsumeHeader (fuzzed_data_provider, base.GetHash (), base.nBits );
170- FinalizeHeader (header);
172+ FinalizeHeader (header, chainman );
171173 base = header;
172174 }
173175
176+ all_headers.insert (all_headers.end (), headers.begin (), headers.end ());
177+
174178 auto headers_msg = NetMsg::Make (NetMsgType::HEADERS, TX_WITH_WITNESS (headers));
175179 g_testing_setup->SendMessage (fuzzed_data_provider, std::move (headers_msg));
176180 },
@@ -179,16 +183,28 @@ FUZZ_TARGET(p2p_headers_presync, .init = initialize)
179183 auto block = finalized_block ();
180184 CBlockHeaderAndShortTxIDs cmpct_block{block, fuzzed_data_provider.ConsumeIntegral <uint64_t >()};
181185
186+ all_headers.push_back (block);
187+
182188 auto headers_msg = NetMsg::Make (NetMsgType::CMPCTBLOCK, TX_WITH_WITNESS (cmpct_block));
183189 g_testing_setup->SendMessage (fuzzed_data_provider, std::move (headers_msg));
184190 },
185191 [&]() NO_THREAD_SAFETY_ANALYSIS {
186192 // Send a block
187193 auto block = finalized_block ();
188194
195+ all_headers.push_back (block);
196+
189197 auto headers_msg = NetMsg::Make (NetMsgType::BLOCK, TX_WITH_WITNESS (block));
190198 g_testing_setup->SendMessage (fuzzed_data_provider, std::move (headers_msg));
191199 });
200+
201+ // This is a conservative overestimate, as base is only moved forward when sending headers. In theory,
202+ // the longest chain generated by this test is 1600 (FUZZ_MAX_HEADERS_RESULTS * 100) headers. In that case,
203+ // this variable will accurately reflect the chain's total work.
204+ total_work += CalculateClaimedHeadersWork (all_headers);
205+
206+ // This test should never create a chain with more work than MinimumChainWork.
207+ assert (total_work < chainman.MinimumChainWork ());
192208 }
193209
194210 // The headers/blocks sent in this test should never be stored, as the chains don't have the work required
0 commit comments