Skip to content

Commit 284bd17

Browse files
committed
add check that chainwork doesn't exceed minimum work
1 parent 9aa5d1c commit 284bd17

File tree

1 file changed

+24
-8
lines changed

1 file changed

+24
-8
lines changed

src/test/fuzz/p2p_headers_presync.cpp

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
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

1516
namespace {
@@ -20,9 +21,7 @@ class HeadersSyncSetup : public TestingSetup
2021
std::vector<CNode*> m_connections;
2122

2223
public:
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

Comments
 (0)