mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 14:59:39 -04:00
add check that chainwork doesn't exceed minimum work
This commit is contained in:
parent
9aa5d1c3fc
commit
284bd17309
1 changed files with 24 additions and 8 deletions
|
@ -10,6 +10,7 @@
|
||||||
#include <test/util/net.h>
|
#include <test/util/net.h>
|
||||||
#include <test/util/script.h>
|
#include <test/util/script.h>
|
||||||
#include <test/util/setup_common.h>
|
#include <test/util/setup_common.h>
|
||||||
|
#include <uint256.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -20,9 +21,7 @@ class HeadersSyncSetup : public TestingSetup
|
||||||
std::vector<CNode*> m_connections;
|
std::vector<CNode*> m_connections;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HeadersSyncSetup(const ChainType chain_type = ChainType::MAIN,
|
HeadersSyncSetup(const ChainType chain_type, TestOpts opts) : TestingSetup(chain_type, opts)
|
||||||
TestOpts opts = {})
|
|
||||||
: TestingSetup(chain_type, opts)
|
|
||||||
{
|
{
|
||||||
PeerManager::Options peerman_opts;
|
PeerManager::Options peerman_opts;
|
||||||
node::ApplyArgsManOptions(*m_node.args, peerman_opts);
|
node::ApplyArgsManOptions(*m_node.args, peerman_opts);
|
||||||
|
@ -116,9 +115,9 @@ CBlock ConsumeBlock(FuzzedDataProvider& fuzzed_data_provider, const uint256& pre
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FinalizeHeader(CBlockHeader& header)
|
void FinalizeHeader(CBlockHeader& header, const ChainstateManager& chainman)
|
||||||
{
|
{
|
||||||
while (!CheckProofOfWork(header.GetHash(), header.nBits, Params().GetConsensus())) {
|
while (!CheckProofOfWork(header.GetHash(), header.nBits, chainman.GetParams().GetConsensus())) {
|
||||||
++(header.nNonce);
|
++(header.nNonce);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,17 +143,20 @@ FUZZ_TARGET(p2p_headers_presync, .init = initialize)
|
||||||
|
|
||||||
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
|
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
|
||||||
|
|
||||||
CBlockHeader base{Params().GenesisBlock()};
|
CBlockHeader base{chainman.GetParams().GenesisBlock()};
|
||||||
SetMockTime(base.nTime);
|
SetMockTime(base.nTime);
|
||||||
|
|
||||||
// The chain is just a single block, so this is equal to 1
|
// The chain is just a single block, so this is equal to 1
|
||||||
size_t original_index_size{WITH_LOCK(cs_main, return chainman.m_blockman.m_block_index.size())};
|
size_t original_index_size{WITH_LOCK(cs_main, return chainman.m_blockman.m_block_index.size())};
|
||||||
|
arith_uint256 total_work{WITH_LOCK(cs_main, return chainman.m_best_header->nChainWork)};
|
||||||
|
|
||||||
|
std::vector<CBlockHeader> all_headers;
|
||||||
|
|
||||||
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 100)
|
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 100)
|
||||||
{
|
{
|
||||||
auto finalized_block = [&]() {
|
auto finalized_block = [&]() {
|
||||||
CBlock block = ConsumeBlock(fuzzed_data_provider, base.GetHash(), base.nBits);
|
CBlock block = ConsumeBlock(fuzzed_data_provider, base.GetHash(), base.nBits);
|
||||||
FinalizeHeader(block);
|
FinalizeHeader(block, chainman);
|
||||||
return block;
|
return block;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -167,10 +169,12 @@ FUZZ_TARGET(p2p_headers_presync, .init = initialize)
|
||||||
headers.resize(FUZZ_MAX_HEADERS_RESULTS);
|
headers.resize(FUZZ_MAX_HEADERS_RESULTS);
|
||||||
for (CBlock& header : headers) {
|
for (CBlock& header : headers) {
|
||||||
header = ConsumeHeader(fuzzed_data_provider, base.GetHash(), base.nBits);
|
header = ConsumeHeader(fuzzed_data_provider, base.GetHash(), base.nBits);
|
||||||
FinalizeHeader(header);
|
FinalizeHeader(header, chainman);
|
||||||
base = header;
|
base = header;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
all_headers.insert(all_headers.end(), headers.begin(), headers.end());
|
||||||
|
|
||||||
auto headers_msg = NetMsg::Make(NetMsgType::HEADERS, TX_WITH_WITNESS(headers));
|
auto headers_msg = NetMsg::Make(NetMsgType::HEADERS, TX_WITH_WITNESS(headers));
|
||||||
g_testing_setup->SendMessage(fuzzed_data_provider, std::move(headers_msg));
|
g_testing_setup->SendMessage(fuzzed_data_provider, std::move(headers_msg));
|
||||||
},
|
},
|
||||||
|
@ -179,6 +183,8 @@ FUZZ_TARGET(p2p_headers_presync, .init = initialize)
|
||||||
auto block = finalized_block();
|
auto block = finalized_block();
|
||||||
CBlockHeaderAndShortTxIDs cmpct_block{block, fuzzed_data_provider.ConsumeIntegral<uint64_t>()};
|
CBlockHeaderAndShortTxIDs cmpct_block{block, fuzzed_data_provider.ConsumeIntegral<uint64_t>()};
|
||||||
|
|
||||||
|
all_headers.push_back(block);
|
||||||
|
|
||||||
auto headers_msg = NetMsg::Make(NetMsgType::CMPCTBLOCK, TX_WITH_WITNESS(cmpct_block));
|
auto headers_msg = NetMsg::Make(NetMsgType::CMPCTBLOCK, TX_WITH_WITNESS(cmpct_block));
|
||||||
g_testing_setup->SendMessage(fuzzed_data_provider, std::move(headers_msg));
|
g_testing_setup->SendMessage(fuzzed_data_provider, std::move(headers_msg));
|
||||||
},
|
},
|
||||||
|
@ -186,9 +192,19 @@ FUZZ_TARGET(p2p_headers_presync, .init = initialize)
|
||||||
// Send a block
|
// Send a block
|
||||||
auto block = finalized_block();
|
auto block = finalized_block();
|
||||||
|
|
||||||
|
all_headers.push_back(block);
|
||||||
|
|
||||||
auto headers_msg = NetMsg::Make(NetMsgType::BLOCK, TX_WITH_WITNESS(block));
|
auto headers_msg = NetMsg::Make(NetMsgType::BLOCK, TX_WITH_WITNESS(block));
|
||||||
g_testing_setup->SendMessage(fuzzed_data_provider, std::move(headers_msg));
|
g_testing_setup->SendMessage(fuzzed_data_provider, std::move(headers_msg));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// This is a conservative overestimate, as base is only moved forward when sending headers. In theory,
|
||||||
|
// the longest chain generated by this test is 1600 (FUZZ_MAX_HEADERS_RESULTS * 100) headers. In that case,
|
||||||
|
// this variable will accurately reflect the chain's total work.
|
||||||
|
total_work += CalculateClaimedHeadersWork(all_headers);
|
||||||
|
|
||||||
|
// This test should never create a chain with more work than MinimumChainWork.
|
||||||
|
assert(total_work < chainman.MinimumChainWork());
|
||||||
}
|
}
|
||||||
|
|
||||||
// The headers/blocks sent in this test should never be stored, as the chains don't have the work required
|
// The headers/blocks sent in this test should never be stored, as the chains don't have the work required
|
||||||
|
|
Loading…
Add table
Reference in a new issue