mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-09-13 06:04:42 +02:00
Merge bitcoin/bitcoin#35856: fuzz: cover the mempool interface for transaction announcement
dd2561003dfuzz: cover the mempool interface for transaction announcement (Antoine Poinsot) Pull request description: This adds coverage in the existing `tx_pool` harness for the `ExtractBestByMiningScoreWithTopology` method recently added in #34628. ACKs for top commit: dergoegge: utACKdd2561003dTree-SHA512: 3e2ea6afff080f48f5b519c49cb6ef51a76eb20186bcfcb5d8cf194f67aa99bf5f5683271b58b97c9bc4e521ea3e08a46ee019e0ffc028222db9dbcb383c48fd
This commit is contained in:
@@ -116,6 +116,32 @@ void SetMempoolConstraints(ArgsManager& args, FuzzedDataProvider& fuzzed_data_pr
|
||||
ToString(fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 999)));
|
||||
}
|
||||
|
||||
/** Get a list of wtxids to query from the mempool for relay. Make the list heterogeneous with
|
||||
* wtxids of mempool transactions, non-mempool transactions, and duplicates. */
|
||||
std::vector<Wtxid> WtxidsToRelay(FuzzedDataProvider& fuzzed_data_provider, const MockedTxPool& tx_pool)
|
||||
{
|
||||
LOCK(tx_pool.cs);
|
||||
std::vector<Wtxid> res;
|
||||
|
||||
uint8_t dummy{0};
|
||||
const auto mempool_entries{tx_pool.entryAll()};
|
||||
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 100) {
|
||||
if (!mempool_entries.empty() && fuzzed_data_provider.ConsumeBool()) {
|
||||
// Wtxid of an in-mempool transaction
|
||||
const auto& entry_ref{PickValue(fuzzed_data_provider, mempool_entries).get()};
|
||||
res.push_back(entry_ref.GetTx().GetWitnessHash());
|
||||
// Don't remove it from the mempool, so the next pick is possibly a duplicate
|
||||
} else {
|
||||
// Wtxid of a not-in-mempool transaction
|
||||
res.push_back(Wtxid::FromUint256(uint256{dummy}));
|
||||
// Possibly make the next wtxid of a not-in-mempool transaction, a duplicate
|
||||
if (fuzzed_data_provider.ConsumeBool()) dummy++;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void Finish(FuzzedDataProvider& fuzzed_data_provider, MockedTxPool& tx_pool, Chainstate& chainstate)
|
||||
{
|
||||
WITH_LOCK(::cs_main, tx_pool.check(chainstate.CoinsTip(), chainstate.m_chain.Height() + 1));
|
||||
@@ -151,6 +177,28 @@ void Finish(FuzzedDataProvider& fuzzed_data_provider, MockedTxPool& tx_pool, Cha
|
||||
assert(tx_pool.size() < info_all.size());
|
||||
}
|
||||
|
||||
// Query a number of mempool entries as if to relay them, and assert some invariants on the result.
|
||||
auto wtxids_to_relay{WtxidsToRelay(fuzzed_data_provider, tx_pool)};
|
||||
const auto wtxids_count_before{wtxids_to_relay.size()};
|
||||
const auto n_to_sort{fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 100)};
|
||||
const auto sorted_iter{WITH_LOCK(tx_pool.cs, return tx_pool.ExtractBestByMiningScoreWithTopology(wtxids_to_relay, n_to_sort))};
|
||||
const auto expected_count{std::min(n_to_sort, wtxids_count_before)};
|
||||
// We removed at least as many transactions from the list as we expected sorted entries.
|
||||
Assert(wtxids_to_relay.size() <= wtxids_count_before - expected_count);
|
||||
// When there is enough non-duplicate in-mempool transactions (list of remaining wtxids is
|
||||
// non-empty), we must have received the expected number of entries.
|
||||
Assert(sorted_iter.size() == expected_count || wtxids_to_relay.empty());
|
||||
if (n_to_sort > 0) {
|
||||
// If we asked for a positive number of entries, we must have removed all wtxids that do
|
||||
// not correspond to a mempool entry..
|
||||
const auto is_in_mempool = [&](const auto& wtxid) EXCLUSIVE_LOCKS_REQUIRED(tx_pool.cs) { return tx_pool.GetIter(wtxid).has_value(); };
|
||||
Assert(WITH_LOCK(tx_pool.cs, return std::ranges::all_of(wtxids_to_relay, is_in_mempool)));
|
||||
// ..As well as all duplicates.
|
||||
const auto wtxids_count{wtxids_to_relay.size()};
|
||||
const std::set<Wtxid> unique_wtxids{std::make_move_iterator(wtxids_to_relay.begin()), std::make_move_iterator(wtxids_to_relay.end())};
|
||||
Assert(unique_wtxids.size() == wtxids_count);
|
||||
}
|
||||
|
||||
if (fuzzed_data_provider.ConsumeBool()) {
|
||||
// Try eviction
|
||||
LOCK2(::cs_main, tx_pool.cs);
|
||||
|
||||
Reference in New Issue
Block a user