net: optimize compact block extra tx iteration
What changed, and why it matters
This is a small performance cleanup in Bitcoin Core's network code. A temporary cache used when reconstructing compact blocks used to be fully sized up front, meaning the code would repeatedly scan empty placeholder slots. The change instead grows the cache only as it fills, so reconstruction skips unused slots. There is no direct security vulnerability being fixed; it is an optimization that may slightly reduce CPU work during block reconstruction.
Treat as a routine performance improvement. No urgent security action required. Reviewers may want to confirm that the ring-buffer index vExtraTxnForCompactIt still wraps correctly and that reserve() does not change behavior once the cache is full.
Security signals we found
Performance optimization in compact block reconstruction path
Avoids scanning default/empty entries in vExtraTxnForCompact
No bounds-check, memory-safety, or validation logic changed
Evidence from the diff
In PeerManagerImpl::AddToCompactExtraTransactions(), vExtraTxnForCompact was previously resized to m_opts.max_extra_txs on first insertion, creating default {Wtxid::ZERO, nullptr} entries for all unused slots. Compact block reconstruction would then scan those empty entries. The patch reserves capacity but only appends live entries until the cache is full, preserving the ring-buffer overwrite behavior once full. This avoids scanning default-constructed entries before the cache reaches capacity.
Changed components
src/net_processing.cppPeerManagerImpl::AddToCompactExtraTransactions()Compact block reconstruction / extra transaction cacheInspect captured patch +7 / −5
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 61b8a4ec..0b6d8fa7 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -1907,11 +1907,13 @@ std::vector<CTransactionRef> PeerManagerImpl::AbortPrivateBroadcast(const uint25
void PeerManagerImpl::AddToCompactExtraTransactions(const CTransactionRef& tx)
{
- if (m_opts.max_extra_txs <= 0)
- return;
- if (!vExtraTxnForCompact.size())
- vExtraTxnForCompact.resize(m_opts.max_extra_txs);
- vExtraTxnForCompact[vExtraTxnForCompactIt] = std::make_pair(tx->GetWitnessHash(), tx);
+ if (m_opts.max_extra_txs == 0) return;
+ if (vExtraTxnForCompact.size() < m_opts.max_extra_txs) {
+ if (vExtraTxnForCompact.empty()) vExtraTxnForCompact.reserve(m_opts.max_extra_txs);
+ vExtraTxnForCompact.emplace_back(tx->GetWitnessHash(), tx);
+ } else {
+ vExtraTxnForCompact[vExtraTxnForCompactIt] = std::make_pair(tx->GetWitnessHash(), tx);
+ }
vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
}
Why this scored 16/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.