Skip to content

Commit e107bf7

Browse files
committed
[fuzz] TxOrphanage::SanityCheck accounting
1 parent 22dccea commit e107bf7

File tree

4 files changed

+48
-1
lines changed

4 files changed

+48
-1
lines changed

src/test/fuzz/txdownloadman.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ static void CheckInvariants(const node::TxDownloadManagerImpl& txdownload_impl,
285285

286286
// Orphanage usage should never exceed what is allowed
287287
Assert(orphanage.Size() <= max_orphan_count);
288+
txdownload_impl.m_orphanage.SanityCheck();
288289

289290
// We should never have more than the maximum in-flight requests out for a peer.
290291
for (NodeId peer = 0; peer < NUM_PEERS; ++peer) {
@@ -437,8 +438,8 @@ FUZZ_TARGET(txdownloadman_impl, .init = initialize)
437438
auto time_skip = fuzzed_data_provider.PickValueInArray(TIME_SKIPS);
438439
if (fuzzed_data_provider.ConsumeBool()) time_skip *= -1;
439440
time += time_skip;
440-
CheckInvariants(txdownload_impl, max_orphan_count);
441441
}
442+
CheckInvariants(txdownload_impl, max_orphan_count);
442443
// Disconnect everybody, check that all data structures are empty.
443444
for (NodeId nodeid = 0; nodeid < NUM_PEERS; ++nodeid) {
444445
txdownload_impl.DisconnectedPeer(nodeid);

src/test/fuzz/txorphan.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ FUZZ_TARGET(txorphan, .init = initialize_orphanage)
204204
});
205205

206206
}
207+
207208
// Set tx as potential parent to be used for future GetChildren() calls.
208209
if (!ptx_potential_parent || fuzzed_data_provider.ConsumeBool()) {
209210
ptx_potential_parent = tx;
@@ -213,4 +214,5 @@ FUZZ_TARGET(txorphan, .init = initialize_orphanage)
213214
const bool get_tx_nonnull{orphanage.GetTx(tx->GetWitnessHash()) != nullptr};
214215
Assert(have_tx == get_tx_nonnull);
215216
}
217+
orphanage.SanityCheck();
216218
}

src/txorphanage.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,3 +321,43 @@ std::vector<TxOrphanage::OrphanTxBase> TxOrphanage::GetOrphanTransactions() cons
321321
}
322322
return ret;
323323
}
324+
325+
void TxOrphanage::SanityCheck() const
326+
{
327+
// Check that cached m_total_announcements is correct
328+
unsigned int counted_total_announcements{0};
329+
// Check that m_total_orphan_usage is correct
330+
unsigned int counted_total_usage{0};
331+
332+
// Check that cached PeerOrphanInfo::m_total_size is correct
333+
std::map<NodeId, unsigned int> counted_size_per_peer;
334+
335+
for (const auto& [wtxid, orphan] : m_orphans) {
336+
counted_total_announcements += orphan.announcers.size();
337+
counted_total_usage += orphan.GetUsage();
338+
339+
Assume(!orphan.announcers.empty());
340+
for (const auto& peer : orphan.announcers) {
341+
auto& count_peer_entry = counted_size_per_peer.try_emplace(peer).first->second;
342+
count_peer_entry += orphan.GetUsage();
343+
}
344+
}
345+
346+
Assume(m_total_announcements >= m_orphans.size());
347+
Assume(counted_total_announcements == m_total_announcements);
348+
Assume(counted_total_usage == m_total_orphan_usage);
349+
350+
// There must be an entry in m_peer_orphanage_info for each peer
351+
// However, there may be m_peer_orphanage_info entries corresponding to peers for whom we
352+
// previously had orphans but no longer do.
353+
Assume(counted_size_per_peer.size() <= m_peer_orphanage_info.size());
354+
355+
for (const auto& [peerid, info] : m_peer_orphanage_info) {
356+
auto it_counted = counted_size_per_peer.find(peerid);
357+
if (it_counted == counted_size_per_peer.end()) {
358+
Assume(info.m_total_usage == 0);
359+
} else {
360+
Assume(it_counted->second == info.m_total_usage);
361+
}
362+
}
363+
}

src/txorphanage.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ class TxOrphanage {
105105
return peer_it == m_peer_orphanage_info.end() ? 0 : peer_it->second.m_total_usage;
106106
}
107107

108+
/** Check consistency between PeerOrphanInfo and m_orphans. Recalculate counters and ensure they
109+
* match what is cached. */
110+
void SanityCheck() const;
111+
108112
protected:
109113
struct OrphanTx : public OrphanTxBase {
110114
size_t list_pos;

0 commit comments

Comments
 (0)