@@ -39,17 +39,17 @@ void TxDownloadManager::DisconnectedPeer(NodeId nodeid)
39
39
{
40
40
m_impl->DisconnectedPeer (nodeid);
41
41
}
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)
43
43
{
44
44
return m_impl->AddTxAnnouncement (peer, gtxid, now);
45
45
}
46
46
std::vector<GenTxid> TxDownloadManager::GetRequestsToSend (NodeId nodeid, std::chrono::microseconds current_time)
47
47
{
48
48
return m_impl->GetRequestsToSend (nodeid, current_time);
49
49
}
50
- void TxDownloadManager::ReceivedNotFound (NodeId nodeid, const std::vector<uint256 >& txhashes )
50
+ void TxDownloadManager::ReceivedNotFound (NodeId nodeid, const std::vector<GenTxidVariant >& gtxids )
51
51
{
52
- m_impl->ReceivedNotFound (nodeid, txhashes );
52
+ m_impl->ReceivedNotFound (nodeid, gtxids );
53
53
}
54
54
void TxDownloadManager::MempoolAcceptedTx (const CTransactionRef& tx)
55
55
{
@@ -122,33 +122,28 @@ void TxDownloadManagerImpl::BlockDisconnected()
122
122
RecentConfirmedTransactionsFilter ().reset ();
123
123
}
124
124
125
- bool TxDownloadManagerImpl::AlreadyHaveTx (const GenTxid & gtxid, bool include_reconsiderable)
125
+ bool TxDownloadManagerImpl::AlreadyHaveTx (const GenTxidVariant & gtxid, bool include_reconsiderable)
126
126
{
127
- const uint256& hash = gtxid.GetHash ();
127
+ const uint256& hash = gtxid.ToUint256 ();
128
128
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 ;
146
141
147
142
if (include_reconsiderable && RecentRejectsReconsiderableFilter ().contains (hash)) return true ;
148
143
149
144
if (RecentConfirmedTransactionsFilter ().contains (hash)) return true ;
150
145
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);
152
147
}
153
148
154
149
void TxDownloadManagerImpl::ConnectedPeer (NodeId nodeid, const TxDownloadConnectionInfo& info)
@@ -172,18 +167,17 @@ void TxDownloadManagerImpl::DisconnectedPeer(NodeId nodeid)
172
167
173
168
}
174
169
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)
176
171
{
177
172
// If this is an orphan we are trying to resolve, consider this peer as a orphan resolution candidate instead.
178
173
// - is wtxid matching something in orphanage
179
174
// - exists in orphanage
180
175
// - 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>(>xid)) {
177
+ if (auto orphan_tx{m_orphanage.GetTx (*wtxid)}) {
184
178
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 );
187
181
});
188
182
189
183
// 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,
192
186
return true ;
193
187
}
194
188
195
- if (MaybeAddOrphanResolutionCandidate (unique_parents, wtxid, peer, now)) {
189
+ if (MaybeAddOrphanResolutionCandidate (unique_parents, * wtxid, peer, now)) {
196
190
m_orphanage.AddAnnouncer (orphan_tx->GetWitnessHash (), peer);
197
191
}
198
192
@@ -224,7 +218,7 @@ bool TxDownloadManagerImpl::AddTxAnnouncement(NodeId peer, const GenTxid& gtxid,
224
218
const bool overloaded = !info.m_relay_permissions && m_txrequest.CountInFlight (peer) >= MAX_PEER_TX_REQUEST_IN_FLIGHT;
225
219
if (overloaded) delay += OVERLOADED_PEER_TX_DELAY;
226
220
227
- m_txrequest.ReceivedInv (peer, gtxid, info.m_preferred , now + delay);
221
+ m_txrequest.ReceivedInv (peer, GenTxid::FromVariant ( gtxid) , info.m_preferred , now + delay);
228
222
229
223
return false ;
230
224
}
@@ -277,7 +271,7 @@ std::vector<GenTxid> TxDownloadManagerImpl::GetRequestsToSend(NodeId nodeid, std
277
271
entry.second .GetHash ().ToString (), entry.first );
278
272
}
279
273
for (const GenTxid& gtxid : requestable) {
280
- if (!AlreadyHaveTx (gtxid, /* include_reconsiderable=*/ false )) {
274
+ if (!AlreadyHaveTx (gtxid. ToVariant () , /* include_reconsiderable=*/ false )) {
281
275
LogDebug (BCLog::NET, " Requesting %s %s peer=%d\n " , gtxid.IsWtxid () ? " wtx" : " tx" ,
282
276
gtxid.GetHash ().ToString (), nodeid);
283
277
requests.emplace_back (gtxid);
@@ -291,12 +285,12 @@ std::vector<GenTxid> TxDownloadManagerImpl::GetRequestsToSend(NodeId nodeid, std
291
285
return requests;
292
286
}
293
287
294
- void TxDownloadManagerImpl::ReceivedNotFound (NodeId nodeid, const std::vector<uint256 >& txhashes )
288
+ void TxDownloadManagerImpl::ReceivedNotFound (NodeId nodeid, const std::vector<GenTxidVariant >& gtxids )
295
289
{
296
- for (const auto & txhash : txhashes ) {
290
+ for (const auto & gtxid : gtxids ) {
297
291
// If we receive a NOTFOUND message for a tx we requested, mark the announcement for it as
298
292
// completed in TxRequestTracker.
299
- m_txrequest.ReceivedResponse (nodeid, txhash );
293
+ m_txrequest.ReceivedResponse (nodeid, gtxid. ToUint256 () );
300
294
}
301
295
}
302
296
@@ -377,13 +371,13 @@ node::RejectedTxTodo TxDownloadManagerImpl::MempoolRejectedTx(const CTransaction
377
371
// Distinguish between parents in m_lazy_recent_rejects and m_lazy_recent_rejects_reconsiderable.
378
372
// We can tolerate having up to 1 parent in m_lazy_recent_rejects_reconsiderable since we
379
373
// 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 () )) {
383
377
fRejectedParents = true ;
384
378
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)) {
387
381
// More than 1 parent in m_lazy_recent_rejects_reconsiderable: 1p1c will not be
388
382
// sufficient to accept this package, so just give up here.
389
383
if (rejected_parent_reconsiderable.has_value ()) {
@@ -397,8 +391,8 @@ node::RejectedTxTodo TxDownloadManagerImpl::MempoolRejectedTx(const CTransaction
397
391
// Filter parents that we already have.
398
392
// Exclude m_lazy_recent_rejects_reconsiderable: the missing parent may have been
399
393
// 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 );
402
396
});
403
397
const auto now{GetTime<std::chrono::microseconds>()};
404
398
const auto & wtxid = ptx->GetWitnessHash ();
@@ -412,8 +406,8 @@ node::RejectedTxTodo TxDownloadManagerImpl::MempoolRejectedTx(const CTransaction
412
406
//
413
407
// Search by txid and, if the tx has a witness, wtxid
414
408
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);
417
411
418
412
for (const auto & nodeid : orphan_resolution_candidates) {
419
413
if (MaybeAddOrphanResolutionCandidate (unique_parents, ptx->GetWitnessHash (), nodeid, now)) {
@@ -515,8 +509,8 @@ void TxDownloadManagerImpl::MempoolRejectedPackage(const Package& package)
515
509
516
510
std::pair<bool , std::optional<PackageToValidate>> TxDownloadManagerImpl::ReceivedTx (NodeId nodeid, const CTransactionRef& ptx)
517
511
{
518
- const uint256 & txid = ptx->GetHash ();
519
- const uint256 & wtxid = ptx->GetWitnessHash ();
512
+ const Txid & txid = ptx->GetHash ();
513
+ const Wtxid & wtxid = ptx->GetWitnessHash ();
520
514
521
515
// Mark that we have received a response
522
516
m_txrequest.ReceivedResponse (nodeid, txid);
@@ -535,7 +529,7 @@ std::pair<bool, std::optional<PackageToValidate>> TxDownloadManagerImpl::Receive
535
529
// already; and an adversary can already relay us old transactions
536
530
// (older than our recency filter) if trying to DoS us, without any need
537
531
// for witness malleation.
538
- if (AlreadyHaveTx (GenTxid::Wtxid ( wtxid) , /* include_reconsiderable=*/ false )) {
532
+ if (AlreadyHaveTx (wtxid, /* include_reconsiderable=*/ false )) {
539
533
// If a tx is detected by m_lazy_recent_rejects it is ignored. Because we haven't
540
534
// submitted the tx to our mempool, we won't have computed a DoS
541
535
// score for it or determined exactly why we consider it invalid.
@@ -552,7 +546,7 @@ std::pair<bool, std::optional<PackageToValidate>> TxDownloadManagerImpl::Receive
552
546
// peer simply for relaying a tx that our m_lazy_recent_rejects has caught,
553
547
// regardless of false positives.
554
548
return {false , std::nullopt};
555
- } else if (RecentRejectsReconsiderableFilter ().contains (wtxid)) {
549
+ } else if (RecentRejectsReconsiderableFilter ().contains (wtxid. ToUint256 () )) {
556
550
// When a transaction is already in m_lazy_recent_rejects_reconsiderable, we shouldn't submit
557
551
// it by itself again. However, look for a matching child in the orphanage, as it is
558
552
// possible that they succeed as a package.
0 commit comments