Skip to content

Commit dc78ed2

Browse files
committed
Merge bitcoin/bitcoin#33005: refactor: GenTxid type safety followups
94b39ce refactor: Change `m_tx_inventory_to_send` from `std::set<GenTxid>` to `std::set<Wtxid>` (marcofleon) a9819b0 refactor: Change `FindTxForGetData` to take GenTxid instead of CInv (marcofleon) d588575 refactor: miscellaneous GenTxid followups (marcofleon) Pull request description: This is a followup to bitcoin/bitcoin#32631. Addresses: bitcoin/bitcoin#32631 (comment) bitcoin/bitcoin#32631 (comment) bitcoin/bitcoin#32631 (comment) bitcoin/bitcoin#32631 (comment) bitcoin/bitcoin#32631 (comment) ACKs for top commit: glozow: ACK 94b39ce maflcko: review ACK 94b39ce 🎲 stickies-v: ACK 94b39ce Tree-SHA512: 3c88656b2e4e676653db87df5b1b694e1b1f40d89d7b825dad068e57c9c9f8add098ba797413274bd992b1c1fdec94c794ab3fd086d2a9561f5de92ae9f6d942
2 parents 3cb65ff + 94b39ce commit dc78ed2

File tree

6 files changed

+46
-43
lines changed

6 files changed

+46
-43
lines changed

src/net_processing.cpp

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -298,11 +298,11 @@ struct Peer {
298298
* us or we have announced to the peer. We use this to avoid announcing
299299
* the same (w)txid to a peer that already has the transaction. */
300300
CRollingBloomFilter m_tx_inventory_known_filter GUARDED_BY(m_tx_inventory_mutex){50000, 0.000001};
301-
/** Set of transaction ids we still have to announce (txid for
302-
* non-wtxid-relay peers, wtxid for wtxid-relay peers). We use the
303-
* mempool to sort transactions in dependency order before relay, so
304-
* this does not have to be sorted. */
305-
std::set<GenTxid> m_tx_inventory_to_send GUARDED_BY(m_tx_inventory_mutex);
301+
/** Set of wtxids we still have to announce. For non-wtxid-relay peers,
302+
* we retrieve the txid from the corresponding mempool transaction when
303+
* constructing the `inv` message. We use the mempool to sort transactions
304+
* in dependency order before relay, so this does not have to be sorted. */
305+
std::set<Wtxid> m_tx_inventory_to_send GUARDED_BY(m_tx_inventory_mutex);
306306
/** Whether the peer has requested us to send our complete mempool. Only
307307
* permitted if the peer has NetPermissionFlags::Mempool or we advertise
308308
* NODE_BLOOM. See BIP35. */
@@ -947,7 +947,7 @@ class PeerManagerImpl final : public PeerManager
947947
std::atomic<std::chrono::seconds> m_last_tip_update{0s};
948948

949949
/** Determine whether or not a peer can request a transaction, and return it (or nullptr if not found or not allowed). */
950-
CTransactionRef FindTxForGetData(const Peer::TxRelay& tx_relay, const CInv& inv)
950+
CTransactionRef FindTxForGetData(const Peer::TxRelay& tx_relay, const GenTxid& gtxid)
951951
EXCLUSIVE_LOCKS_REQUIRED(!m_most_recent_block_mutex, NetEventsInterface::g_msgproc_mutex);
952952

953953
void ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic<bool>& interruptMsgProc)
@@ -2166,9 +2166,9 @@ void PeerManagerImpl::RelayTransaction(const Txid& txid, const Wtxid& wtxid)
21662166
// in the announcement.
21672167
if (tx_relay->m_next_inv_send_time == 0s) continue;
21682168

2169-
const auto gtxid{peer.m_wtxid_relay ? GenTxid{wtxid} : GenTxid{txid}};
2170-
if (!tx_relay->m_tx_inventory_known_filter.contains(gtxid.ToUint256())) {
2171-
tx_relay->m_tx_inventory_to_send.insert(gtxid);
2169+
const uint256& hash{peer.m_wtxid_relay ? wtxid.ToUint256() : txid.ToUint256()};
2170+
if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2171+
tx_relay->m_tx_inventory_to_send.insert(wtxid);
21722172
}
21732173
}
21742174
}
@@ -2391,15 +2391,14 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv&
23912391
}
23922392
}
23932393

2394-
CTransactionRef PeerManagerImpl::FindTxForGetData(const Peer::TxRelay& tx_relay, const CInv& inv)
2394+
CTransactionRef PeerManagerImpl::FindTxForGetData(const Peer::TxRelay& tx_relay, const GenTxid& gtxid)
23952395
{
2396-
auto gtxid{ToGenTxid(inv)};
2397-
// If a tx was in the mempool prior to the last INV for this peer, permit the request.
23982396
auto txinfo{std::visit(
23992397
[&](const auto& id) EXCLUSIVE_LOCKS_REQUIRED(NetEventsInterface::g_msgproc_mutex) {
24002398
return m_mempool.info_for_relay(id, tx_relay.m_last_inv_sequence);
24012399
},
24022400
gtxid)};
2401+
24032402
if (txinfo.tx) {
24042403
return std::move(txinfo.tx);
24052404
}
@@ -2442,7 +2441,7 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic
24422441
continue;
24432442
}
24442443

2445-
if (auto tx{FindTxForGetData(*tx_relay, inv)}) {
2444+
if (auto tx{FindTxForGetData(*tx_relay, ToGenTxid(inv))}) {
24462445
// WTX and WITNESS_TX imply we serialize with witness
24472446
const auto maybe_with_witness = (inv.IsMsgTx() ? TX_NO_WITNESS : TX_WITH_WITNESS);
24482447
MakeAndPushMessage(pfrom, NetMsgType::TX, maybe_with_witness(*tx));
@@ -5440,7 +5439,7 @@ class CompareInvMempoolOrder
54405439
public:
54415440
explicit CompareInvMempoolOrder(CTxMemPool* mempool) : m_mempool{mempool} {}
54425441

5443-
bool operator()(std::set<GenTxid>::iterator a, std::set<GenTxid>::iterator b)
5442+
bool operator()(std::set<Wtxid>::iterator a, std::set<Wtxid>::iterator b)
54445443
{
54455444
/* As std::make_heap produces a max-heap, we want the entries with the
54465445
* fewest ancestors/highest fee to sort later. */
@@ -5756,13 +5755,12 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
57565755
LOCK(tx_relay->m_bloom_filter_mutex);
57575756

57585757
for (const auto& txinfo : vtxinfo) {
5759-
CInv inv{
5760-
peer->m_wtxid_relay ? MSG_WTX : MSG_TX,
5761-
peer->m_wtxid_relay ?
5762-
txinfo.tx->GetWitnessHash().ToUint256() :
5763-
txinfo.tx->GetHash().ToUint256(),
5764-
};
5765-
tx_relay->m_tx_inventory_to_send.erase(ToGenTxid(inv));
5758+
const Txid& txid{txinfo.tx->GetHash()};
5759+
const Wtxid& wtxid{txinfo.tx->GetWitnessHash()};
5760+
const auto inv = peer->m_wtxid_relay ?
5761+
CInv{MSG_WTX, wtxid.ToUint256()} :
5762+
CInv{MSG_TX, txid.ToUint256()};
5763+
tx_relay->m_tx_inventory_to_send.erase(wtxid);
57665764

57675765
// Don't send transactions that peers will not put into their mempool
57685766
if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
@@ -5783,9 +5781,9 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
57835781
// Determine transactions to relay
57845782
if (fSendTrickle) {
57855783
// Produce a vector with all candidates for sending
5786-
std::vector<std::set<GenTxid>::iterator> vInvTx;
5784+
std::vector<std::set<Wtxid>::iterator> vInvTx;
57875785
vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
5788-
for (std::set<GenTxid>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
5786+
for (std::set<Wtxid>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
57895787
vInvTx.push_back(it);
57905788
}
57915789
const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
@@ -5802,22 +5800,26 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
58025800
while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
58035801
// Fetch the top element from the heap
58045802
std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5805-
std::set<GenTxid>::iterator it = vInvTx.back();
5803+
std::set<Wtxid>::iterator it = vInvTx.back();
58065804
vInvTx.pop_back();
5807-
GenTxid hash = *it;
5808-
Assume(peer->m_wtxid_relay == hash.IsWtxid());
5809-
CInv inv(peer->m_wtxid_relay ? MSG_WTX : MSG_TX, hash.ToUint256());
5805+
auto wtxid = *it;
58105806
// Remove it from the to-be-sent set
58115807
tx_relay->m_tx_inventory_to_send.erase(it);
5812-
// Check if not in the filter already
5813-
if (tx_relay->m_tx_inventory_known_filter.contains(hash.ToUint256())) {
5814-
continue;
5815-
}
58165808
// Not in the mempool anymore? don't bother sending it.
5817-
auto txinfo{std::visit([&](const auto& id) { return m_mempool.info(id); }, hash)};
5809+
auto txinfo = m_mempool.info(wtxid);
58185810
if (!txinfo.tx) {
58195811
continue;
58205812
}
5813+
// `TxRelay::m_tx_inventory_known_filter` contains either txids or wtxids
5814+
// depending on whether our peer supports wtxid-relay. Therefore, first
5815+
// construct the inv and then use its hash for the filter check.
5816+
const auto inv = peer->m_wtxid_relay ?
5817+
CInv{MSG_WTX, wtxid.ToUint256()} :
5818+
CInv{MSG_TX, txinfo.tx->GetHash().ToUint256()};
5819+
// Check if not in the filter already
5820+
if (tx_relay->m_tx_inventory_known_filter.contains(inv.hash)) {
5821+
continue;
5822+
}
58215823
// Peer told you to not send transactions at that feerate? Don't bother sending it.
58225824
if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
58235825
continue;
@@ -5830,7 +5832,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
58305832
MakeAndPushMessage(*pto, NetMsgType::INV, vInv);
58315833
vInv.clear();
58325834
}
5833-
tx_relay->m_tx_inventory_known_filter.insert(hash.ToUint256());
5835+
tx_relay->m_tx_inventory_known_filter.insert(inv.hash);
58345836
}
58355837

58365838
// Ensure we'll respond to GETDATA requests for anything we've just announced

src/txmempool.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -793,17 +793,17 @@ void CTxMemPool::check(const CCoinsViewCache& active_coins_tip, int64_t spendhei
793793
assert(innerUsage == cachedInnerUsage);
794794
}
795795

796-
bool CTxMemPool::CompareDepthAndScore(const GenTxid& hasha, const GenTxid& hashb) const
796+
bool CTxMemPool::CompareDepthAndScore(const Wtxid& hasha, const Wtxid& hashb) const
797797
{
798798
/* Return `true` if hasha should be considered sooner than hashb. Namely when:
799799
* a is not in the mempool, but b is
800800
* both are in the mempool and a has fewer ancestors than b
801801
* both are in the mempool and a has a higher score than b
802802
*/
803803
LOCK(cs);
804-
auto j{std::visit([&](const auto& id) EXCLUSIVE_LOCKS_REQUIRED(cs) { return GetIter(id); }, hashb)};
804+
auto j{GetIter(hashb)};
805805
if (!j.has_value()) return false;
806-
auto i{std::visit([&](const auto& id) EXCLUSIVE_LOCKS_REQUIRED(cs) { return GetIter(id); }, hasha)};
806+
auto i{GetIter(hasha)};
807807
if (!i.has_value()) return true;
808808
uint64_t counta = i.value()->GetCountWithAncestors();
809809
uint64_t countb = j.value()->GetCountWithAncestors();
@@ -961,9 +961,9 @@ const CTransaction* CTxMemPool::GetConflictTx(const COutPoint& prevout) const
961961

962962
std::optional<CTxMemPool::txiter> CTxMemPool::GetIter(const Txid& txid) const
963963
{
964+
AssertLockHeld(cs);
964965
auto it = mapTx.find(txid.ToUint256());
965-
if (it != mapTx.end()) return it;
966-
return std::nullopt;
966+
return it != mapTx.end() ? std::make_optional(it) : std::nullopt;
967967
}
968968

969969
std::optional<CTxMemPool::txiter> CTxMemPool::GetIter(const Wtxid& wtxid) const

src/txmempool.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ class CTxMemPool
448448
void removeConflicts(const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(cs);
449449
void removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight) EXCLUSIVE_LOCKS_REQUIRED(cs);
450450

451-
bool CompareDepthAndScore(const GenTxid& hasha, const GenTxid& hashb) const;
451+
bool CompareDepthAndScore(const Wtxid& hasha, const Wtxid& hashb) const;
452452
bool isSpent(const COutPoint& outpoint) const;
453453
unsigned int GetTransactionsUpdated() const;
454454
void AddTransactionsUpdated(unsigned int n);

src/txrequest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ class TxRequestTracker::Impl {
595595

596596
//! Find the GenTxids to request now from peer.
597597
std::vector<GenTxid> GetRequestable(NodeId peer, std::chrono::microseconds now,
598-
std::vector<std::pair<NodeId, GenTxid>>* expired)
598+
std::vector<std::pair<NodeId, GenTxid>>* expired)
599599
{
600600
// Move time.
601601
SetTimePoint(now, expired);
@@ -746,7 +746,7 @@ void TxRequestTracker::ReceivedResponse(NodeId peer, const uint256& txhash)
746746
}
747747

748748
std::vector<GenTxid> TxRequestTracker::GetRequestable(NodeId peer, std::chrono::microseconds now,
749-
std::vector<std::pair<NodeId, GenTxid>>* expired)
749+
std::vector<std::pair<NodeId, GenTxid>>* expired)
750750
{
751751
return m_impl->GetRequestable(peer, now, expired);
752752
}

src/txrequest.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ class TxRequestTracker {
164164
* simultaneously by one peer, and end up being requested from them, the requests will happen in announcement order.
165165
*/
166166
std::vector<GenTxid> GetRequestable(NodeId peer, std::chrono::microseconds now,
167-
std::vector<std::pair<NodeId, GenTxid>>* expired = nullptr);
167+
std::vector<std::pair<NodeId, GenTxid>>* expired = nullptr);
168168

169169
/** Marks a transaction as requested, with a specified expiry.
170170
*

src/util/transaction_identifier.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ class GenTxid : public std::variant<Txid, Wtxid>
9898

9999
friend auto operator<=>(const GenTxid& a, const GenTxid& b)
100100
{
101-
return std::tuple(a.IsWtxid(), a.ToUint256()) <=> std::tuple(b.IsWtxid(), b.ToUint256());
101+
// Use a reference for read-only access to the hash, avoiding a copy that might not be optimized away.
102+
return std::tuple<bool, const uint256&>(a.IsWtxid(), a.ToUint256()) <=> std::tuple<bool, const uint256&>(b.IsWtxid(), b.ToUint256());
102103
}
103104
};
104105

0 commit comments

Comments
 (0)