Skip to content

Commit bde4579

Browse files
committed
Convert txdownloadman_impl to GenTxidVariant
Convert all of `txdownloadman_impl` to the new variant except for `GetRequestsToSend`, which will be easier to switch at the same time as `txrequest`.
1 parent c876a89 commit bde4579

File tree

6 files changed

+75
-82
lines changed

6 files changed

+75
-82
lines changed

src/net_processing.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4015,7 +4015,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
40154015
AddKnownTx(*peer, inv.hash);
40164016

40174017
if (!m_chainman.IsInitialBlockDownload()) {
4018-
const bool fAlreadyHave{m_txdownloadman.AddTxAnnouncement(pfrom.GetId(), gtxid, current_time)};
4018+
const bool fAlreadyHave{m_txdownloadman.AddTxAnnouncement(pfrom.GetId(), gtxid.ToVariant(), current_time)};
40194019
LogDebug(BCLog::NET, "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom.GetId());
40204020
}
40214021
} else {
@@ -4942,11 +4942,11 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
49424942
if (msg_type == NetMsgType::NOTFOUND) {
49434943
std::vector<CInv> vInv;
49444944
vRecv >> vInv;
4945-
std::vector<uint256> tx_invs;
4945+
std::vector<GenTxidVariant> tx_invs;
49464946
if (vInv.size() <= node::MAX_PEER_TX_ANNOUNCEMENTS + MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
49474947
for (CInv &inv : vInv) {
49484948
if (inv.IsGenTxMsg()) {
4949-
tx_invs.emplace_back(inv.hash);
4949+
tx_invs.emplace_back(ToGenTxid(inv).ToVariant());
49504950
}
49514951
}
49524952
}

src/node/txdownloadman.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@
88
#include <net.h>
99
#include <policy/packages.h>
1010
#include <txorphanage.h>
11+
#include <util/transaction_identifier.h>
1112

1213
#include <cstdint>
1314
#include <memory>
1415

1516
class CBlock;
1617
class CRollingBloomFilter;
1718
class CTxMemPool;
18-
class GenTxid;
19+
class GenTxidVariant;
1920
class TxRequestTracker;
2021
namespace node {
2122
class TxDownloadManagerImpl;
@@ -137,13 +138,13 @@ class TxDownloadManager {
137138
/** Consider adding this tx hash to txrequest. Should be called whenever a new inv has been received.
138139
* Also called internally when a transaction is missing parents so that we can request them.
139140
* Returns true if this was a dropped inv (p2p_inv=true and we already have the tx), false otherwise. */
140-
bool AddTxAnnouncement(NodeId peer, const GenTxid& gtxid, std::chrono::microseconds now);
141+
bool AddTxAnnouncement(NodeId peer, const GenTxidVariant& gtxid, std::chrono::microseconds now);
141142

142143
/** Get getdata requests to send. */
143144
std::vector<GenTxid> GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time);
144145

145146
/** Should be called when a notfound for a tx has been received. */
146-
void ReceivedNotFound(NodeId nodeid, const std::vector<uint256>& txhashes);
147+
void ReceivedNotFound(NodeId nodeid, const std::vector<GenTxidVariant>& gtxids);
147148

148149
/** Respond to successful transaction submission to mempool */
149150
void MempoolAcceptedTx(const CTransactionRef& tx);

src/node/txdownloadman_impl.cpp

Lines changed: 42 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,17 @@ void TxDownloadManager::DisconnectedPeer(NodeId nodeid)
3939
{
4040
m_impl->DisconnectedPeer(nodeid);
4141
}
42-
bool TxDownloadManager::AddTxAnnouncement(NodeId peer, const GenTxid& gtxid, std::chrono::microseconds now)
42+
bool TxDownloadManager::AddTxAnnouncement(NodeId peer, const GenTxidVariant& gtxid, std::chrono::microseconds now)
4343
{
4444
return m_impl->AddTxAnnouncement(peer, gtxid, now);
4545
}
4646
std::vector<GenTxid> TxDownloadManager::GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time)
4747
{
4848
return m_impl->GetRequestsToSend(nodeid, current_time);
4949
}
50-
void TxDownloadManager::ReceivedNotFound(NodeId nodeid, const std::vector<uint256>& txhashes)
50+
void TxDownloadManager::ReceivedNotFound(NodeId nodeid, const std::vector<GenTxidVariant>& gtxids)
5151
{
52-
m_impl->ReceivedNotFound(nodeid, txhashes);
52+
m_impl->ReceivedNotFound(nodeid, gtxids);
5353
}
5454
void TxDownloadManager::MempoolAcceptedTx(const CTransactionRef& tx)
5555
{
@@ -122,33 +122,28 @@ void TxDownloadManagerImpl::BlockDisconnected()
122122
RecentConfirmedTransactionsFilter().reset();
123123
}
124124

125-
bool TxDownloadManagerImpl::AlreadyHaveTx(const GenTxid& gtxid, bool include_reconsiderable)
125+
bool TxDownloadManagerImpl::AlreadyHaveTx(const GenTxidVariant& gtxid, bool include_reconsiderable)
126126
{
127-
const uint256& hash = gtxid.GetHash();
127+
const uint256& hash = gtxid.ToUint256();
128128

129-
if (gtxid.IsWtxid()) {
130-
// Normal query by wtxid.
131-
if (m_orphanage.HaveTx(Wtxid::FromUint256(hash))) return true;
132-
} else {
133-
// Never query by txid: it is possible that the transaction in the orphanage has the same
134-
// txid but a different witness, which would give us a false positive result. If we decided
135-
// not to request the transaction based on this result, an attacker could prevent us from
136-
// downloading a transaction by intentionally creating a malleated version of it. While
137-
// only one (or none!) of these transactions can ultimately be confirmed, we have no way of
138-
// discerning which one that is, so the orphanage can store multiple transactions with the
139-
// same txid.
140-
//
141-
// While we won't query by txid, we can try to "guess" what the wtxid is based on the txid.
142-
// A non-segwit transaction's txid == wtxid. Query this txid "casted" to a wtxid. This will
143-
// help us find non-segwit transactions, saving bandwidth, and should have no false positives.
144-
if (m_orphanage.HaveTx(Wtxid::FromUint256(hash))) return true;
145-
}
129+
// Never query by txid: it is possible that the transaction in the orphanage has the same
130+
// txid but a different witness, which would give us a false positive result. If we decided
131+
// not to request the transaction based on this result, an attacker could prevent us from
132+
// downloading a transaction by intentionally creating a malleated version of it. While
133+
// only one (or none!) of these transactions can ultimately be confirmed, we have no way of
134+
// discerning which one that is, so the orphanage can store multiple transactions with the
135+
// same txid.
136+
//
137+
// While we won't query by txid, we can try to "guess" what the wtxid is based on the txid.
138+
// A non-segwit transaction's txid == wtxid. Query this txhash "casted" to a wtxid. This will
139+
// help us find non-segwit transactions, saving bandwidth, and should have no false positives.
140+
if (m_orphanage.HaveTx(Wtxid::FromUint256(hash))) return true;
146141

147142
if (include_reconsiderable && RecentRejectsReconsiderableFilter().contains(hash)) return true;
148143

149144
if (RecentConfirmedTransactionsFilter().contains(hash)) return true;
150145

151-
return RecentRejectsFilter().contains(hash) || std::visit([&](const auto& id) { return m_opts.m_mempool.exists(id); }, gtxid.ToVariant());
146+
return RecentRejectsFilter().contains(hash) || std::visit([&](const auto& id) { return m_opts.m_mempool.exists(id); }, gtxid);
152147
}
153148

154149
void TxDownloadManagerImpl::ConnectedPeer(NodeId nodeid, const TxDownloadConnectionInfo& info)
@@ -172,18 +167,17 @@ void TxDownloadManagerImpl::DisconnectedPeer(NodeId nodeid)
172167

173168
}
174169

175-
bool TxDownloadManagerImpl::AddTxAnnouncement(NodeId peer, const GenTxid& gtxid, std::chrono::microseconds now)
170+
bool TxDownloadManagerImpl::AddTxAnnouncement(NodeId peer, const GenTxidVariant& gtxid, std::chrono::microseconds now)
176171
{
177172
// If this is an orphan we are trying to resolve, consider this peer as a orphan resolution candidate instead.
178173
// - is wtxid matching something in orphanage
179174
// - exists in orphanage
180175
// - peer can be an orphan resolution candidate
181-
if (gtxid.IsWtxid()) {
182-
const auto wtxid{Wtxid::FromUint256(gtxid.GetHash())};
183-
if (auto orphan_tx{m_orphanage.GetTx(wtxid)}) {
176+
if (const auto* wtxid = std::get_if<Wtxid>(&gtxid)) {
177+
if (auto orphan_tx{m_orphanage.GetTx(*wtxid)}) {
184178
auto unique_parents{GetUniqueParents(*orphan_tx)};
185-
std::erase_if(unique_parents, [&](const auto& txid){
186-
return AlreadyHaveTx(GenTxid::Txid(txid), /*include_reconsiderable=*/false);
179+
std::erase_if(unique_parents, [&](const auto& txid) {
180+
return AlreadyHaveTx(txid, /*include_reconsiderable=*/false);
187181
});
188182

189183
// The missing parents may have all been rejected or accepted since the orphan was added to the orphanage.
@@ -192,7 +186,7 @@ bool TxDownloadManagerImpl::AddTxAnnouncement(NodeId peer, const GenTxid& gtxid,
192186
return true;
193187
}
194188

195-
if (MaybeAddOrphanResolutionCandidate(unique_parents, wtxid, peer, now)) {
189+
if (MaybeAddOrphanResolutionCandidate(unique_parents, *wtxid, peer, now)) {
196190
m_orphanage.AddAnnouncer(orphan_tx->GetWitnessHash(), peer);
197191
}
198192

@@ -224,7 +218,7 @@ bool TxDownloadManagerImpl::AddTxAnnouncement(NodeId peer, const GenTxid& gtxid,
224218
const bool overloaded = !info.m_relay_permissions && m_txrequest.CountInFlight(peer) >= MAX_PEER_TX_REQUEST_IN_FLIGHT;
225219
if (overloaded) delay += OVERLOADED_PEER_TX_DELAY;
226220

227-
m_txrequest.ReceivedInv(peer, gtxid, info.m_preferred, now + delay);
221+
m_txrequest.ReceivedInv(peer, GenTxid::FromVariant(gtxid), info.m_preferred, now + delay);
228222

229223
return false;
230224
}
@@ -277,7 +271,7 @@ std::vector<GenTxid> TxDownloadManagerImpl::GetRequestsToSend(NodeId nodeid, std
277271
entry.second.GetHash().ToString(), entry.first);
278272
}
279273
for (const GenTxid& gtxid : requestable) {
280-
if (!AlreadyHaveTx(gtxid, /*include_reconsiderable=*/false)) {
274+
if (!AlreadyHaveTx(gtxid.ToVariant(), /*include_reconsiderable=*/false)) {
281275
LogDebug(BCLog::NET, "Requesting %s %s peer=%d\n", gtxid.IsWtxid() ? "wtx" : "tx",
282276
gtxid.GetHash().ToString(), nodeid);
283277
requests.emplace_back(gtxid);
@@ -291,12 +285,12 @@ std::vector<GenTxid> TxDownloadManagerImpl::GetRequestsToSend(NodeId nodeid, std
291285
return requests;
292286
}
293287

294-
void TxDownloadManagerImpl::ReceivedNotFound(NodeId nodeid, const std::vector<uint256>& txhashes)
288+
void TxDownloadManagerImpl::ReceivedNotFound(NodeId nodeid, const std::vector<GenTxidVariant>& gtxids)
295289
{
296-
for (const auto& txhash : txhashes) {
290+
for (const auto& gtxid : gtxids) {
297291
// If we receive a NOTFOUND message for a tx we requested, mark the announcement for it as
298292
// completed in TxRequestTracker.
299-
m_txrequest.ReceivedResponse(nodeid, txhash);
293+
m_txrequest.ReceivedResponse(nodeid, gtxid.ToUint256());
300294
}
301295
}
302296

@@ -377,13 +371,13 @@ node::RejectedTxTodo TxDownloadManagerImpl::MempoolRejectedTx(const CTransaction
377371
// Distinguish between parents in m_lazy_recent_rejects and m_lazy_recent_rejects_reconsiderable.
378372
// We can tolerate having up to 1 parent in m_lazy_recent_rejects_reconsiderable since we
379373
// submit 1p1c packages. However, fail immediately if any are in m_lazy_recent_rejects.
380-
std::optional<uint256> rejected_parent_reconsiderable;
381-
for (const uint256& parent_txid : unique_parents) {
382-
if (RecentRejectsFilter().contains(parent_txid)) {
374+
std::optional<Txid> rejected_parent_reconsiderable;
375+
for (const Txid& parent_txid : unique_parents) {
376+
if (RecentRejectsFilter().contains(parent_txid.ToUint256())) {
383377
fRejectedParents = true;
384378
break;
385-
} else if (RecentRejectsReconsiderableFilter().contains(parent_txid) &&
386-
!m_opts.m_mempool.exists(Txid::FromUint256(parent_txid))) {
379+
} else if (RecentRejectsReconsiderableFilter().contains(parent_txid.ToUint256()) &&
380+
!m_opts.m_mempool.exists(parent_txid)) {
387381
// More than 1 parent in m_lazy_recent_rejects_reconsiderable: 1p1c will not be
388382
// sufficient to accept this package, so just give up here.
389383
if (rejected_parent_reconsiderable.has_value()) {
@@ -397,8 +391,8 @@ node::RejectedTxTodo TxDownloadManagerImpl::MempoolRejectedTx(const CTransaction
397391
// Filter parents that we already have.
398392
// Exclude m_lazy_recent_rejects_reconsiderable: the missing parent may have been
399393
// previously rejected for being too low feerate. This orphan might CPFP it.
400-
std::erase_if(unique_parents, [&](const auto& txid){
401-
return AlreadyHaveTx(GenTxid::Txid(txid), /*include_reconsiderable=*/false);
394+
std::erase_if(unique_parents, [&](const auto& txid) {
395+
return AlreadyHaveTx(txid, /*include_reconsiderable=*/false);
402396
});
403397
const auto now{GetTime<std::chrono::microseconds>()};
404398
const auto& wtxid = ptx->GetWitnessHash();
@@ -412,8 +406,8 @@ node::RejectedTxTodo TxDownloadManagerImpl::MempoolRejectedTx(const CTransaction
412406
//
413407
// Search by txid and, if the tx has a witness, wtxid
414408
std::vector<NodeId> orphan_resolution_candidates{nodeid};
415-
m_txrequest.GetCandidatePeers(ptx->GetHash().ToUint256(), orphan_resolution_candidates);
416-
if (ptx->HasWitness()) m_txrequest.GetCandidatePeers(ptx->GetWitnessHash().ToUint256(), orphan_resolution_candidates);
409+
m_txrequest.GetCandidatePeers(ptx->GetHash(), orphan_resolution_candidates);
410+
if (ptx->HasWitness()) m_txrequest.GetCandidatePeers(ptx->GetWitnessHash(), orphan_resolution_candidates);
417411

418412
for (const auto& nodeid : orphan_resolution_candidates) {
419413
if (MaybeAddOrphanResolutionCandidate(unique_parents, ptx->GetWitnessHash(), nodeid, now)) {
@@ -515,8 +509,8 @@ void TxDownloadManagerImpl::MempoolRejectedPackage(const Package& package)
515509

516510
std::pair<bool, std::optional<PackageToValidate>> TxDownloadManagerImpl::ReceivedTx(NodeId nodeid, const CTransactionRef& ptx)
517511
{
518-
const uint256& txid = ptx->GetHash();
519-
const uint256& wtxid = ptx->GetWitnessHash();
512+
const Txid& txid = ptx->GetHash();
513+
const Wtxid& wtxid = ptx->GetWitnessHash();
520514

521515
// Mark that we have received a response
522516
m_txrequest.ReceivedResponse(nodeid, txid);
@@ -535,7 +529,7 @@ std::pair<bool, std::optional<PackageToValidate>> TxDownloadManagerImpl::Receive
535529
// already; and an adversary can already relay us old transactions
536530
// (older than our recency filter) if trying to DoS us, without any need
537531
// for witness malleation.
538-
if (AlreadyHaveTx(GenTxid::Wtxid(wtxid), /*include_reconsiderable=*/false)) {
532+
if (AlreadyHaveTx(wtxid, /*include_reconsiderable=*/false)) {
539533
// If a tx is detected by m_lazy_recent_rejects it is ignored. Because we haven't
540534
// submitted the tx to our mempool, we won't have computed a DoS
541535
// score for it or determined exactly why we consider it invalid.
@@ -552,7 +546,7 @@ std::pair<bool, std::optional<PackageToValidate>> TxDownloadManagerImpl::Receive
552546
// peer simply for relaying a tx that our m_lazy_recent_rejects has caught,
553547
// regardless of false positives.
554548
return {false, std::nullopt};
555-
} else if (RecentRejectsReconsiderableFilter().contains(wtxid)) {
549+
} else if (RecentRejectsReconsiderableFilter().contains(wtxid.ToUint256())) {
556550
// When a transaction is already in m_lazy_recent_rejects_reconsiderable, we shouldn't submit
557551
// it by itself again. However, look for a matching child in the orphanage, as it is
558552
// possible that they succeed as a package.

src/node/txdownloadman_impl.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,21 +155,21 @@ class TxDownloadManagerImpl {
155155
* - m_recent_rejects_reconsiderable (if include_reconsiderable = true)
156156
* - m_recent_confirmed_transactions
157157
* */
158-
bool AlreadyHaveTx(const GenTxid& gtxid, bool include_reconsiderable);
158+
bool AlreadyHaveTx(const GenTxidVariant& gtxid, bool include_reconsiderable);
159159

160160
void ConnectedPeer(NodeId nodeid, const TxDownloadConnectionInfo& info);
161161
void DisconnectedPeer(NodeId nodeid);
162162

163163
/** Consider adding this tx hash to txrequest. Should be called whenever a new inv has been received.
164164
* Also called internally when a transaction is missing parents so that we can request them.
165165
*/
166-
bool AddTxAnnouncement(NodeId peer, const GenTxid& gtxid, std::chrono::microseconds now);
166+
bool AddTxAnnouncement(NodeId peer, const GenTxidVariant& gtxid, std::chrono::microseconds now);
167167

168168
/** Get getdata requests to send. */
169169
std::vector<GenTxid> GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time);
170170

171171
/** Marks a tx as ReceivedResponse in txrequest. */
172-
void ReceivedNotFound(NodeId nodeid, const std::vector<uint256>& txhashes);
172+
void ReceivedNotFound(NodeId nodeid, const std::vector<GenTxidVariant>& gtxids);
173173

174174
/** Look for a child of this transaction in the orphanage to form a 1-parent-1-child package,
175175
* skipping any combinations that have already been tried. Return the resulting package along with

0 commit comments

Comments
 (0)