Skip to content

Commit f61d9e4

Browse files
committed
[refactor] move AlreadyHaveTx to TxDownload
This is move-only. Also delete external RecentConfirmedTransactionsFilter() access since it is no longer necessary.
1 parent 84e4ef8 commit f61d9e4

File tree

4 files changed

+50
-60
lines changed

4 files changed

+50
-60
lines changed

src/net_processing.cpp

Lines changed: 4 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -854,17 +854,6 @@ class PeerManagerImpl final : public PeerManager
854854
/** Stalling timeout for blocks in IBD */
855855
std::atomic<std::chrono::seconds> m_block_stalling_timeout{BLOCK_STALLING_TIMEOUT_DEFAULT};
856856

857-
/** Check whether we already have this gtxid in:
858-
* - mempool
859-
* - orphanage
860-
* - m_lazy_recent_rejects
861-
* - m_lazy_recent_rejects_reconsiderable (if include_reconsiderable = true)
862-
* - m_lazy_recent_confirmed_transactions
863-
* */
864-
bool AlreadyHaveTx(const GenTxid& gtxid, bool include_reconsiderable)
865-
EXCLUSIVE_LOCKS_REQUIRED(m_tx_download_mutex);
866-
867-
868857
CRollingBloomFilter& RecentRejectsFilter() EXCLUSIVE_LOCKS_REQUIRED(m_tx_download_mutex)
869858
{
870859
AssertLockHeld(m_tx_download_mutex);
@@ -877,12 +866,6 @@ class PeerManagerImpl final : public PeerManager
877866
return m_txdownloadman.RecentRejectsReconsiderableFilter();
878867
}
879868

880-
CRollingBloomFilter& RecentConfirmedTransactionsFilter() EXCLUSIVE_LOCKS_REQUIRED(m_tx_download_mutex)
881-
{
882-
AssertLockHeld(m_tx_download_mutex);
883-
return m_txdownloadman.RecentConfirmedTransactionsFilter();
884-
}
885-
886869
/**
887870
* For sending `inv`s to inbound peers, we use a single (exponentially
888871
* distributed) timer for all peers. If we used a separate timer for each
@@ -2214,40 +2197,6 @@ void PeerManagerImpl::BlockChecked(const CBlock& block, const BlockValidationSta
22142197
// Messages
22152198
//
22162199

2217-
2218-
bool PeerManagerImpl::AlreadyHaveTx(const GenTxid& gtxid, bool include_reconsiderable)
2219-
{
2220-
AssertLockHeld(m_tx_download_mutex);
2221-
2222-
auto& m_orphanage = m_txdownloadman.GetOrphanageRef();
2223-
2224-
const uint256& hash = gtxid.GetHash();
2225-
2226-
if (gtxid.IsWtxid()) {
2227-
// Normal query by wtxid.
2228-
if (m_orphanage.HaveTx(Wtxid::FromUint256(hash))) return true;
2229-
} else {
2230-
// Never query by txid: it is possible that the transaction in the orphanage has the same
2231-
// txid but a different witness, which would give us a false positive result. If we decided
2232-
// not to request the transaction based on this result, an attacker could prevent us from
2233-
// downloading a transaction by intentionally creating a malleated version of it. While
2234-
// only one (or none!) of these transactions can ultimately be confirmed, we have no way of
2235-
// discerning which one that is, so the orphanage can store multiple transactions with the
2236-
// same txid.
2237-
//
2238-
// While we won't query by txid, we can try to "guess" what the wtxid is based on the txid.
2239-
// A non-segwit transaction's txid == wtxid. Query this txid "casted" to a wtxid. This will
2240-
// help us find non-segwit transactions, saving bandwidth, and should have no false positives.
2241-
if (m_orphanage.HaveTx(Wtxid::FromUint256(hash))) return true;
2242-
}
2243-
2244-
if (include_reconsiderable && RecentRejectsReconsiderableFilter().contains(hash)) return true;
2245-
2246-
if (RecentConfirmedTransactionsFilter().contains(hash)) return true;
2247-
2248-
return RecentRejectsFilter().contains(hash) || m_mempool.exists(gtxid);
2249-
}
2250-
22512200
bool PeerManagerImpl::AlreadyHaveBlock(const uint256& block_hash)
22522201
{
22532202
return m_chainman.m_blockman.LookupBlockIndex(block_hash) != nullptr;
@@ -4172,7 +4121,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
41724121
return;
41734122
}
41744123
const GenTxid gtxid = ToGenTxid(inv);
4175-
const bool fAlreadyHave = AlreadyHaveTx(gtxid, /*include_reconsiderable=*/true);
4124+
const bool fAlreadyHave = m_txdownloadman.AlreadyHaveTx(gtxid, /*include_reconsiderable=*/true);
41764125
LogDebug(BCLog::NET, "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom.GetId());
41774126

41784127
AddKnownTx(*peer, inv.hash);
@@ -4487,7 +4436,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
44874436
// already; and an adversary can already relay us old transactions
44884437
// (older than our recency filter) if trying to DoS us, without any need
44894438
// for witness malleation.
4490-
if (AlreadyHaveTx(GenTxid::Wtxid(wtxid), /*include_reconsiderable=*/true)) {
4439+
if (m_txdownloadman.AlreadyHaveTx(GenTxid::Wtxid(wtxid), /*include_reconsiderable=*/true)) {
44914440
if (pfrom.HasPermission(NetPermissionFlags::ForceRelay)) {
44924441
// Always relay transactions received from peers with forcerelay
44934442
// permission, even if they were already in the mempool, allowing
@@ -4586,7 +4535,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
45864535
AddKnownTx(*peer, parent_txid);
45874536
// Exclude m_lazy_recent_rejects_reconsiderable: the missing parent may have been
45884537
// previously rejected for being too low feerate. This orphan might CPFP it.
4589-
if (!AlreadyHaveTx(gtxid, /*include_reconsiderable=*/false)) AddTxAnnouncement(pfrom, gtxid, current_time);
4538+
if (!m_txdownloadman.AlreadyHaveTx(gtxid, /*include_reconsiderable=*/false)) AddTxAnnouncement(pfrom, gtxid, current_time);
45904539
}
45914540

45924541
if (m_orphanage.AddTx(ptx, pfrom.GetId())) {
@@ -6259,7 +6208,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
62596208
for (const GenTxid& gtxid : requestable) {
62606209
// Exclude m_lazy_recent_rejects_reconsiderable: we may be requesting a missing parent
62616210
// that was previously rejected for being too low feerate.
6262-
if (!AlreadyHaveTx(gtxid, /*include_reconsiderable=*/false)) {
6211+
if (!m_txdownloadman.AlreadyHaveTx(gtxid, /*include_reconsiderable=*/false)) {
62636212
LogDebug(BCLog::NET, "Requesting %s %s peer=%d\n", gtxid.IsWtxid() ? "wtx" : "tx",
62646213
gtxid.GetHash().ToString(), pto->GetId());
62656214
vGetData.emplace_back(gtxid.IsWtxid() ? MSG_WTX : (MSG_TX | GetFetchFlags(*peer)), gtxid.GetHash());

src/node/txdownloadman.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
class CBlock;
1212
class CRollingBloomFilter;
1313
class CTxMemPool;
14+
class GenTxid;
1415
class TxOrphanage;
1516
class TxRequestTracker;
1617
namespace node {
@@ -53,12 +54,20 @@ class TxDownloadManager {
5354
TxRequestTracker& GetTxRequestRef();
5455
CRollingBloomFilter& RecentRejectsFilter();
5556
CRollingBloomFilter& RecentRejectsReconsiderableFilter();
56-
CRollingBloomFilter& RecentConfirmedTransactionsFilter();
5757

5858
// Responses to chain events. TxDownloadManager is not an actual client of ValidationInterface, these are called through PeerManager.
5959
void ActiveTipChange();
6060
void BlockConnected(const std::shared_ptr<const CBlock>& pblock);
6161
void BlockDisconnected();
62+
63+
/** Check whether we already have this gtxid in:
64+
* - mempool
65+
* - orphanage
66+
* - m_recent_rejects
67+
* - m_recent_rejects_reconsiderable (if include_reconsiderable = true)
68+
* - m_recent_confirmed_transactions
69+
* */
70+
bool AlreadyHaveTx(const GenTxid& gtxid, bool include_reconsiderable);
6271
};
6372
} // namespace node
6473
#endif // BITCOIN_NODE_TXDOWNLOADMAN_H

src/node/txdownloadman_impl.cpp

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,6 @@ CRollingBloomFilter& TxDownloadManager::RecentRejectsReconsiderableFilter()
3434
{
3535
return m_impl->RecentRejectsReconsiderableFilter();
3636
}
37-
CRollingBloomFilter& TxDownloadManager::RecentConfirmedTransactionsFilter()
38-
{
39-
return m_impl->RecentConfirmedTransactionsFilter();
40-
}
4137
void TxDownloadManager::ActiveTipChange()
4238
{
4339
m_impl->ActiveTipChange();
@@ -50,6 +46,10 @@ void TxDownloadManager::BlockDisconnected()
5046
{
5147
m_impl->BlockDisconnected();
5248
}
49+
bool TxDownloadManager::AlreadyHaveTx(const GenTxid& gtxid, bool include_reconsiderable)
50+
{
51+
return m_impl->AlreadyHaveTx(gtxid, include_reconsiderable);
52+
}
5353

5454
// TxDownloadManagerImpl
5555
void TxDownloadManagerImpl::ActiveTipChange()
@@ -84,4 +84,33 @@ void TxDownloadManagerImpl::BlockDisconnected()
8484
// should be just after a new block containing it is found.
8585
RecentConfirmedTransactionsFilter().reset();
8686
}
87+
88+
bool TxDownloadManagerImpl::AlreadyHaveTx(const GenTxid& gtxid, bool include_reconsiderable)
89+
{
90+
const uint256& hash = gtxid.GetHash();
91+
92+
if (gtxid.IsWtxid()) {
93+
// Normal query by wtxid.
94+
if (m_orphanage.HaveTx(Wtxid::FromUint256(hash))) return true;
95+
} else {
96+
// Never query by txid: it is possible that the transaction in the orphanage has the same
97+
// txid but a different witness, which would give us a false positive result. If we decided
98+
// not to request the transaction based on this result, an attacker could prevent us from
99+
// downloading a transaction by intentionally creating a malleated version of it. While
100+
// only one (or none!) of these transactions can ultimately be confirmed, we have no way of
101+
// discerning which one that is, so the orphanage can store multiple transactions with the
102+
// same txid.
103+
//
104+
// While we won't query by txid, we can try to "guess" what the wtxid is based on the txid.
105+
// A non-segwit transaction's txid == wtxid. Query this txid "casted" to a wtxid. This will
106+
// help us find non-segwit transactions, saving bandwidth, and should have no false positives.
107+
if (m_orphanage.HaveTx(Wtxid::FromUint256(hash))) return true;
108+
}
109+
110+
if (include_reconsiderable && RecentRejectsReconsiderableFilter().contains(hash)) return true;
111+
112+
if (RecentConfirmedTransactionsFilter().contains(hash)) return true;
113+
114+
return RecentRejectsFilter().contains(hash) || m_opts.m_mempool.exists(gtxid);
115+
}
87116
} // namespace node

src/node/txdownloadman_impl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <common/bloom.h>
1010
#include <kernel/chain.h>
1111
#include <net.h>
12+
#include <primitives/transaction.h>
1213
#include <txorphanage.h>
1314
#include <txrequest.h>
1415

@@ -130,6 +131,8 @@ class TxDownloadManagerImpl {
130131
void ActiveTipChange();
131132
void BlockConnected(const std::shared_ptr<const CBlock>& pblock);
132133
void BlockDisconnected();
134+
135+
bool AlreadyHaveTx(const GenTxid& gtxid, bool include_reconsiderable);
133136
};
134137
} // namespace node
135138
#endif // BITCOIN_NODE_TXDOWNLOADMAN_IMPL_H

0 commit comments

Comments
 (0)