Bitcoin Core  29.1.0
P2P Digital Currency
txdownloadman_impl.cpp
Go to the documentation of this file.
1 // Copyright (c) 2024
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
6 #include <node/txdownloadman.h>
7 
8 #include <chain.h>
9 #include <consensus/validation.h>
10 #include <logging.h>
11 #include <txmempool.h>
12 #include <validation.h>
13 #include <validationinterface.h>
14 
15 namespace node {
16 // TxDownloadManager wrappers
18  m_impl{std::make_unique<TxDownloadManagerImpl>(options)}
19 {}
21 
23 {
24  m_impl->ActiveTipChange();
25 }
26 void TxDownloadManager::BlockConnected(const std::shared_ptr<const CBlock>& pblock)
27 {
28  m_impl->BlockConnected(pblock);
29 }
31 {
32  m_impl->BlockDisconnected();
33 }
35 {
36  m_impl->ConnectedPeer(nodeid, info);
37 }
39 {
40  m_impl->DisconnectedPeer(nodeid);
41 }
42 bool TxDownloadManager::AddTxAnnouncement(NodeId peer, const GenTxid& gtxid, std::chrono::microseconds now)
43 {
44  return m_impl->AddTxAnnouncement(peer, gtxid, now);
45 }
46 std::vector<GenTxid> TxDownloadManager::GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time)
47 {
48  return m_impl->GetRequestsToSend(nodeid, current_time);
49 }
50 void TxDownloadManager::ReceivedNotFound(NodeId nodeid, const std::vector<uint256>& txhashes)
51 {
52  m_impl->ReceivedNotFound(nodeid, txhashes);
53 }
55 {
56  m_impl->MempoolAcceptedTx(tx);
57 }
58 RejectedTxTodo TxDownloadManager::MempoolRejectedTx(const CTransactionRef& ptx, const TxValidationState& state, NodeId nodeid, bool first_time_failure)
59 {
60  return m_impl->MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
61 }
63 {
64  m_impl->MempoolRejectedPackage(package);
65 }
66 std::pair<bool, std::optional<PackageToValidate>> TxDownloadManager::ReceivedTx(NodeId nodeid, const CTransactionRef& ptx)
67 {
68  return m_impl->ReceivedTx(nodeid, ptx);
69 }
71 {
72  return m_impl->HaveMoreWork(nodeid);
73 }
75 {
76  return m_impl->GetTxToReconsider(nodeid);
77 }
79 {
80  m_impl->CheckIsEmpty();
81 }
83 {
84  m_impl->CheckIsEmpty(nodeid);
85 }
86 std::vector<TxOrphanage::OrphanTxBase> TxDownloadManager::GetOrphanTransactions() const
87 {
88  return m_impl->GetOrphanTransactions();
89 }
90 
91 // TxDownloadManagerImpl
93 {
96 }
97 
98 void TxDownloadManagerImpl::BlockConnected(const std::shared_ptr<const CBlock>& pblock)
99 {
100  m_orphanage.EraseForBlock(*pblock);
101 
102  for (const auto& ptx : pblock->vtx) {
103  RecentConfirmedTransactionsFilter().insert(ptx->GetHash().ToUint256());
104  if (ptx->HasWitness()) {
105  RecentConfirmedTransactionsFilter().insert(ptx->GetWitnessHash().ToUint256());
106  }
107  m_txrequest.ForgetTxHash(ptx->GetHash());
108  m_txrequest.ForgetTxHash(ptx->GetWitnessHash());
109  }
110 }
111 
113 {
114  // To avoid relay problems with transactions that were previously
115  // confirmed, clear our filter of recently confirmed transactions whenever
116  // there's a reorg.
117  // This means that in a 1-block reorg (where 1 block is disconnected and
118  // then another block reconnected), our filter will drop to having only one
119  // block's worth of transactions in it, but that should be fine, since
120  // presumably the most common case of relaying a confirmed transaction
121  // should be just after a new block containing it is found.
123 }
124 
125 bool TxDownloadManagerImpl::AlreadyHaveTx(const GenTxid& gtxid, bool include_reconsiderable)
126 {
127  const uint256& hash = gtxid.GetHash();
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  }
146 
147  if (include_reconsiderable && RecentRejectsReconsiderableFilter().contains(hash)) return true;
148 
149  if (RecentConfirmedTransactionsFilter().contains(hash)) return true;
150 
151  return RecentRejectsFilter().contains(hash) || m_opts.m_mempool.exists(gtxid);
152 }
153 
155 {
156  // If already connected (shouldn't happen in practice), exit early.
157  if (m_peer_info.contains(nodeid)) return;
158 
159  m_peer_info.try_emplace(nodeid, info);
160  if (info.m_wtxid_relay) m_num_wtxid_peers += 1;
161 }
162 
164 {
165  m_orphanage.EraseForPeer(nodeid);
167 
168  if (auto it = m_peer_info.find(nodeid); it != m_peer_info.end()) {
169  if (it->second.m_connection_info.m_wtxid_relay) m_num_wtxid_peers -= 1;
170  m_peer_info.erase(it);
171  }
172 
173 }
174 
175 bool TxDownloadManagerImpl::AddTxAnnouncement(NodeId peer, const GenTxid& gtxid, std::chrono::microseconds now)
176 {
177  // If this is an orphan we are trying to resolve, consider this peer as a orphan resolution candidate instead.
178  // - is wtxid matching something in orphanage
179  // - exists in orphanage
180  // - 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)}) {
184  auto unique_parents{GetUniqueParents(*orphan_tx)};
185  std::erase_if(unique_parents, [&](const auto& txid){
186  return AlreadyHaveTx(GenTxid::Txid(txid), /*include_reconsiderable=*/false);
187  });
188 
189  // The missing parents may have all been rejected or accepted since the orphan was added to the orphanage.
190  // Do not delete from the orphanage, as it may be queued for processing.
191  if (unique_parents.empty()) {
192  return true;
193  }
194 
195  if (MaybeAddOrphanResolutionCandidate(unique_parents, wtxid, peer, now)) {
196  m_orphanage.AddAnnouncer(orphan_tx->GetWitnessHash(), peer);
197  }
198 
199  // Return even if the peer isn't an orphan resolution candidate. This would be caught by AlreadyHaveTx.
200  return true;
201  }
202  }
203 
204  // If this is an inv received from a peer and we already have it, we can drop it.
205  if (AlreadyHaveTx(gtxid, /*include_reconsiderable=*/true)) return true;
206 
207  auto it = m_peer_info.find(peer);
208  if (it == m_peer_info.end()) return false;
209  const auto& info = it->second.m_connection_info;
210  if (!info.m_relay_permissions && m_txrequest.Count(peer) >= MAX_PEER_TX_ANNOUNCEMENTS) {
211  // Too many queued announcements for this peer
212  return false;
213  }
214  // Decide the TxRequestTracker parameters for this announcement:
215  // - "preferred": if fPreferredDownload is set (= outbound, or NetPermissionFlags::NoBan permission)
216  // - "reqtime": current time plus delays for:
217  // - NONPREF_PEER_TX_DELAY for announcements from non-preferred connections
218  // - TXID_RELAY_DELAY for txid announcements while wtxid peers are available
219  // - OVERLOADED_PEER_TX_DELAY for announcements from peers which have at least
220  // MAX_PEER_TX_REQUEST_IN_FLIGHT requests in flight (and don't have NetPermissionFlags::Relay).
221  auto delay{0us};
222  if (!info.m_preferred) delay += NONPREF_PEER_TX_DELAY;
223  if (!gtxid.IsWtxid() && m_num_wtxid_peers > 0) delay += TXID_RELAY_DELAY;
224  const bool overloaded = !info.m_relay_permissions && m_txrequest.CountInFlight(peer) >= MAX_PEER_TX_REQUEST_IN_FLIGHT;
225  if (overloaded) delay += OVERLOADED_PEER_TX_DELAY;
226 
227  m_txrequest.ReceivedInv(peer, gtxid, info.m_preferred, now + delay);
228 
229  return false;
230 }
231 
232 bool TxDownloadManagerImpl::MaybeAddOrphanResolutionCandidate(const std::vector<Txid>& unique_parents, const Wtxid& wtxid, NodeId nodeid, std::chrono::microseconds now)
233 {
234  auto it_peer = m_peer_info.find(nodeid);
235  if (it_peer == m_peer_info.end()) return false;
236  if (m_orphanage.HaveTxFromPeer(wtxid, nodeid)) return false;
237 
238  const auto& peer_entry = m_peer_info.at(nodeid);
239  const auto& info = peer_entry.m_connection_info;
240 
241  // TODO: add delays and limits based on the amount of orphan resolution we are already doing
242  // with this peer, how much they are using the orphanage, etc.
243  if (!info.m_relay_permissions) {
244  // This mirrors the delaying and dropping behavior in AddTxAnnouncement in order to preserve
245  // existing behavior: drop if we are tracking too many invs for this peer already. Each
246  // orphan resolution involves at least 1 transaction request which may or may not be
247  // currently tracked in m_txrequest, so we include that in the count.
248  if (m_txrequest.Count(nodeid) + unique_parents.size() > MAX_PEER_TX_ANNOUNCEMENTS) return false;
249  }
250 
251  std::chrono::seconds delay{0s};
252  if (!info.m_preferred) delay += NONPREF_PEER_TX_DELAY;
253  // The orphan wtxid is used, but resolution entails requesting the parents by txid. Sometimes
254  // parent and child are announced and thus requested around the same time, and we happen to
255  // receive child sooner. Waiting a few seconds may allow us to cancel the orphan resolution
256  // request if the parent arrives in that time.
257  if (m_num_wtxid_peers > 0) delay += TXID_RELAY_DELAY;
258  const bool overloaded = !info.m_relay_permissions && m_txrequest.CountInFlight(nodeid) >= MAX_PEER_TX_REQUEST_IN_FLIGHT;
259  if (overloaded) delay += OVERLOADED_PEER_TX_DELAY;
260 
261  // Treat finding orphan resolution candidate as equivalent to the peer announcing all missing parents.
262  // In the future, orphan resolution may include more explicit steps
263  for (const auto& parent_txid : unique_parents) {
264  m_txrequest.ReceivedInv(nodeid, GenTxid::Txid(parent_txid), info.m_preferred, now + delay);
265  }
266  LogDebug(BCLog::TXPACKAGES, "added peer=%d as a candidate for resolving orphan %s\n", nodeid, wtxid.ToString());
267  return true;
268 }
269 
270 std::vector<GenTxid> TxDownloadManagerImpl::GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time)
271 {
272  std::vector<GenTxid> requests;
273  std::vector<std::pair<NodeId, GenTxid>> expired;
274  auto requestable = m_txrequest.GetRequestable(nodeid, current_time, &expired);
275  for (const auto& entry : expired) {
276  LogDebug(BCLog::NET, "timeout of inflight %s %s from peer=%d\n", entry.second.IsWtxid() ? "wtx" : "tx",
277  entry.second.GetHash().ToString(), entry.first);
278  }
279  for (const GenTxid& gtxid : requestable) {
280  if (!AlreadyHaveTx(gtxid, /*include_reconsiderable=*/false)) {
281  LogDebug(BCLog::NET, "Requesting %s %s peer=%d\n", gtxid.IsWtxid() ? "wtx" : "tx",
282  gtxid.GetHash().ToString(), nodeid);
283  requests.emplace_back(gtxid);
284  m_txrequest.RequestedTx(nodeid, gtxid.GetHash(), current_time + GETDATA_TX_INTERVAL);
285  } else {
286  // We have already seen this transaction, no need to download. This is just a belt-and-suspenders, as
287  // this should already be called whenever a transaction becomes AlreadyHaveTx().
288  m_txrequest.ForgetTxHash(gtxid.GetHash());
289  }
290  }
291  return requests;
292 }
293 
294 void TxDownloadManagerImpl::ReceivedNotFound(NodeId nodeid, const std::vector<uint256>& txhashes)
295 {
296  for (const auto& txhash : txhashes) {
297  // If we receive a NOTFOUND message for a tx we requested, mark the announcement for it as
298  // completed in TxRequestTracker.
299  m_txrequest.ReceivedResponse(nodeid, txhash);
300  }
301 }
302 
303 std::optional<PackageToValidate> TxDownloadManagerImpl::Find1P1CPackage(const CTransactionRef& ptx, NodeId nodeid)
304 {
305  const auto& parent_wtxid{ptx->GetWitnessHash()};
306 
307  Assume(RecentRejectsReconsiderableFilter().contains(parent_wtxid.ToUint256()));
308 
309  // Only consider children from this peer. This helps prevent censorship attempts in which an attacker
310  // sends lots of fake children for the parent, and we (unluckily) keep selecting the fake
311  // children instead of the real one provided by the honest peer. Since we track all announcers
312  // of an orphan, this does not exclude parent + orphan pairs that we happened to request from
313  // different peers.
314  const auto cpfp_candidates_same_peer{m_orphanage.GetChildrenFromSamePeer(ptx, nodeid)};
315 
316  // These children should be sorted from newest to oldest. In the (probably uncommon) case
317  // of children that replace each other, this helps us accept the highest feerate (probably the
318  // most recent) one efficiently.
319  for (const auto& child : cpfp_candidates_same_peer) {
320  Package maybe_cpfp_package{ptx, child};
321  if (!RecentRejectsReconsiderableFilter().contains(GetPackageHash(maybe_cpfp_package)) &&
322  !RecentRejectsFilter().contains(child->GetHash().ToUint256())) {
323  return PackageToValidate{ptx, child, nodeid, nodeid};
324  }
325  }
326  return std::nullopt;
327 }
328 
330 {
331  // As this version of the transaction was acceptable, we can forget about any requests for it.
332  // No-op if the tx is not in txrequest.
333  m_txrequest.ForgetTxHash(tx->GetHash());
334  m_txrequest.ForgetTxHash(tx->GetWitnessHash());
335 
337  // If it came from the orphanage, remove it. No-op if the tx is not in txorphanage.
338  m_orphanage.EraseTx(tx->GetWitnessHash());
339 }
340 
342 {
343  std::vector<Txid> unique_parents;
344  unique_parents.reserve(tx.vin.size());
345  for (const CTxIn& txin : tx.vin) {
346  // We start with all parents, and then remove duplicates below.
347  unique_parents.push_back(txin.prevout.hash);
348  }
349 
350  std::sort(unique_parents.begin(), unique_parents.end());
351  unique_parents.erase(std::unique(unique_parents.begin(), unique_parents.end()), unique_parents.end());
352 
353  return unique_parents;
354 }
355 
357 {
358  const CTransaction& tx{*ptx};
359  // Results returned to caller
360  // Whether we should call AddToCompactExtraTransactions at the end
361  bool add_extra_compact_tx{first_time_failure};
362  // Hashes to pass to AddKnownTx later
363  std::vector<Txid> unique_parents;
364  // Populated if failure is reconsiderable and eligible package is found.
365  std::optional<node::PackageToValidate> package_to_validate;
366 
368  // Only process a new orphan if this is a first time failure, as otherwise it must be either
369  // already in orphanage or from 1p1c processing.
370  if (first_time_failure && !RecentRejectsFilter().contains(ptx->GetWitnessHash().ToUint256())) {
371  bool fRejectedParents = false; // It may be the case that the orphans parents have all been rejected
372 
373  // Deduplicate parent txids, so that we don't have to loop over
374  // the same parent txid more than once down below.
375  unique_parents = GetUniqueParents(tx);
376 
377  // Distinguish between parents in m_lazy_recent_rejects and m_lazy_recent_rejects_reconsiderable.
378  // We can tolerate having up to 1 parent in m_lazy_recent_rejects_reconsiderable since we
379  // 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)) {
383  fRejectedParents = true;
384  break;
385  } else if (RecentRejectsReconsiderableFilter().contains(parent_txid) &&
386  !m_opts.m_mempool.exists(GenTxid::Txid(parent_txid))) {
387  // More than 1 parent in m_lazy_recent_rejects_reconsiderable: 1p1c will not be
388  // sufficient to accept this package, so just give up here.
389  if (rejected_parent_reconsiderable.has_value()) {
390  fRejectedParents = true;
391  break;
392  }
393  rejected_parent_reconsiderable = parent_txid;
394  }
395  }
396  if (!fRejectedParents) {
397  // Filter parents that we already have.
398  // Exclude m_lazy_recent_rejects_reconsiderable: the missing parent may have been
399  // 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);
402  });
403  const auto now{GetTime<std::chrono::microseconds>()};
404  const auto& wtxid = ptx->GetWitnessHash();
405  // Potentially flip add_extra_compact_tx to false if tx is already in orphanage, which
406  // means it was already added to vExtraTxnForCompact.
407  add_extra_compact_tx &= !m_orphanage.HaveTx(wtxid);
408 
409  // If there is no candidate for orphan resolution, AddTx will not be called. This means
410  // that if a peer is overloading us with invs and orphans, they will eventually not be
411  // able to add any more transactions to the orphanage.
412  //
413  // Search by txid and, if the tx has a witness, wtxid
414  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);
417 
418  for (const auto& nodeid : orphan_resolution_candidates) {
419  if (MaybeAddOrphanResolutionCandidate(unique_parents, ptx->GetWitnessHash(), nodeid, now)) {
420  m_orphanage.AddTx(ptx, nodeid);
421  }
422  }
423 
424  // Once added to the orphan pool, a tx is considered AlreadyHave, and we shouldn't request it anymore.
425  m_txrequest.ForgetTxHash(tx.GetHash());
426  m_txrequest.ForgetTxHash(tx.GetWitnessHash());
427 
428  // DoS prevention: do not allow m_orphanage to grow unbounded (see CVE-2012-3789)
429  // Note that, if the orphanage reaches capacity, it's possible that we immediately evict
430  // the transaction we just added.
432  } else {
433  unique_parents.clear();
434  LogDebug(BCLog::MEMPOOL, "not keeping orphan with rejected parents %s (wtxid=%s)\n",
435  tx.GetHash().ToString(),
436  tx.GetWitnessHash().ToString());
437  // We will continue to reject this tx since it has rejected
438  // parents so avoid re-requesting it from other peers.
439  // Here we add both the txid and the wtxid, as we know that
440  // regardless of what witness is provided, we will not accept
441  // this, so we don't need to allow for redownload of this txid
442  // from any of our non-wtxidrelay peers.
443  RecentRejectsFilter().insert(tx.GetHash().ToUint256());
444  RecentRejectsFilter().insert(tx.GetWitnessHash().ToUint256());
445  m_txrequest.ForgetTxHash(tx.GetHash());
446  m_txrequest.ForgetTxHash(tx.GetWitnessHash());
447  }
448  }
449  } else if (state.GetResult() == TxValidationResult::TX_WITNESS_STRIPPED) {
450  add_extra_compact_tx = false;
451  } else {
452  // We can add the wtxid of this transaction to our reject filter.
453  // Do not add txids of witness transactions or witness-stripped
454  // transactions to the filter, as they can have been malleated;
455  // adding such txids to the reject filter would potentially
456  // interfere with relay of valid transactions from peers that
457  // do not support wtxid-based relay. See
458  // https://github.com/bitcoin/bitcoin/issues/8279 for details.
459  // We can remove this restriction (and always add wtxids to
460  // the filter even for witness stripped transactions) once
461  // wtxid-based relay is broadly deployed.
462  // See also comments in https://github.com/bitcoin/bitcoin/pull/18044#discussion_r443419034
463  // for concerns around weakening security of unupgraded nodes
464  // if we start doing this too early.
466  // If the result is TX_RECONSIDERABLE, add it to m_lazy_recent_rejects_reconsiderable
467  // because we should not download or submit this transaction by itself again, but may
468  // submit it as part of a package later.
469  RecentRejectsReconsiderableFilter().insert(ptx->GetWitnessHash().ToUint256());
470 
471  if (first_time_failure) {
472  // When a transaction fails for TX_RECONSIDERABLE, look for a matching child in the
473  // orphanage, as it is possible that they succeed as a package.
474  LogDebug(BCLog::TXPACKAGES, "tx %s (wtxid=%s) failed but reconsiderable, looking for child in orphanage\n",
475  ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString());
476  package_to_validate = Find1P1CPackage(ptx, nodeid);
477  }
478  } else {
479  RecentRejectsFilter().insert(ptx->GetWitnessHash().ToUint256());
480  }
481  m_txrequest.ForgetTxHash(ptx->GetWitnessHash());
482  // If the transaction failed for TX_INPUTS_NOT_STANDARD,
483  // then we know that the witness was irrelevant to the policy
484  // failure, since this check depends only on the txid
485  // (the scriptPubKey being spent is covered by the txid).
486  // Add the txid to the reject filter to prevent repeated
487  // processing of this transaction in the event that child
488  // transactions are later received (resulting in
489  // parent-fetching by txid via the orphan-handling logic).
490  // We only add the txid if it differs from the wtxid, to avoid wasting entries in the
491  // rolling bloom filter.
492  if (state.GetResult() == TxValidationResult::TX_INPUTS_NOT_STANDARD && ptx->HasWitness()) {
493  RecentRejectsFilter().insert(ptx->GetHash().ToUint256());
494  m_txrequest.ForgetTxHash(ptx->GetHash());
495  }
496  }
497 
498  // If the tx failed in ProcessOrphanTx, it should be removed from the orphanage unless the
499  // tx was still missing inputs. If the tx was not in the orphanage, EraseTx does nothing and returns 0.
500  if (state.GetResult() != TxValidationResult::TX_MISSING_INPUTS && m_orphanage.EraseTx(ptx->GetWitnessHash()) > 0) {
501  LogDebug(BCLog::TXPACKAGES, " removed orphan tx %s (wtxid=%s)\n", ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString());
502  }
503 
504  return RejectedTxTodo{
505  .m_should_add_extra_compact_tx = add_extra_compact_tx,
506  .m_unique_parents = std::move(unique_parents),
507  .m_package_to_validate = std::move(package_to_validate)
508  };
509 }
510 
512 {
514 }
515 
516 std::pair<bool, std::optional<PackageToValidate>> TxDownloadManagerImpl::ReceivedTx(NodeId nodeid, const CTransactionRef& ptx)
517 {
518  const uint256& txid = ptx->GetHash();
519  const uint256& wtxid = ptx->GetWitnessHash();
520 
521  // Mark that we have received a response
522  m_txrequest.ReceivedResponse(nodeid, txid);
523  if (ptx->HasWitness()) m_txrequest.ReceivedResponse(nodeid, wtxid);
524 
525  // First check if we should drop this tx.
526  // We do the AlreadyHaveTx() check using wtxid, rather than txid - in the
527  // absence of witness malleation, this is strictly better, because the
528  // recent rejects filter may contain the wtxid but rarely contains
529  // the txid of a segwit transaction that has been rejected.
530  // In the presence of witness malleation, it's possible that by only
531  // doing the check with wtxid, we could overlook a transaction which
532  // was confirmed with a different witness, or exists in our mempool
533  // with a different witness, but this has limited downside:
534  // mempool validation does its own lookup of whether we have the txid
535  // already; and an adversary can already relay us old transactions
536  // (older than our recency filter) if trying to DoS us, without any need
537  // for witness malleation.
538  if (AlreadyHaveTx(GenTxid::Wtxid(wtxid), /*include_reconsiderable=*/false)) {
539  // If a tx is detected by m_lazy_recent_rejects it is ignored. Because we haven't
540  // submitted the tx to our mempool, we won't have computed a DoS
541  // score for it or determined exactly why we consider it invalid.
542  //
543  // This means we won't penalize any peer subsequently relaying a DoSy
544  // tx (even if we penalized the first peer who gave it to us) because
545  // we have to account for m_lazy_recent_rejects showing false positives. In
546  // other words, we shouldn't penalize a peer if we aren't *sure* they
547  // submitted a DoSy tx.
548  //
549  // Note that m_lazy_recent_rejects doesn't just record DoSy or invalid
550  // transactions, but any tx not accepted by the mempool, which may be
551  // due to node policy (vs. consensus). So we can't blanket penalize a
552  // peer simply for relaying a tx that our m_lazy_recent_rejects has caught,
553  // regardless of false positives.
554  return {false, std::nullopt};
555  } else if (RecentRejectsReconsiderableFilter().contains(wtxid)) {
556  // When a transaction is already in m_lazy_recent_rejects_reconsiderable, we shouldn't submit
557  // it by itself again. However, look for a matching child in the orphanage, as it is
558  // possible that they succeed as a package.
559  LogDebug(BCLog::TXPACKAGES, "found tx %s (wtxid=%s) in reconsiderable rejects, looking for child in orphanage\n",
560  txid.ToString(), wtxid.ToString());
561  return {false, Find1P1CPackage(ptx, nodeid)};
562  }
563 
564 
565  return {true, std::nullopt};
566 }
567 
569 {
570  return m_orphanage.HaveTxToReconsider(nodeid);
571 }
572 
574 {
575  return m_orphanage.GetTxToReconsider(nodeid);
576 }
577 
579 {
580  assert(m_txrequest.Count(nodeid) == 0);
581  assert(m_orphanage.UsageByPeer(nodeid) == 0);
582 }
584 {
586  assert(m_orphanage.Size() == 0);
587  assert(m_txrequest.Size() == 0);
589 }
590 std::vector<TxOrphanage::OrphanTxBase> TxDownloadManagerImpl::GetOrphanTransactions() const
591 {
593 }
594 } // namespace node
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:423
bool contains(Span< const unsigned char > vKey) const
Definition: bloom.cpp:226
void ReceivedResponse(NodeId peer, const uint256 &txhash)
Converts a CANDIDATE or REQUESTED announcement to a COMPLETED one.
Definition: txrequest.cpp:752
CTransactionRef GetTxToReconsider(NodeId peer)
Extract a transaction from a peer&#39;s work set Returns nullptr if there are no transactions to work on...
int EraseTx(const Wtxid &wtxid)
Erase an orphan by wtxid.
Definition: txorphanage.cpp:72
static constexpr auto OVERLOADED_PEER_TX_DELAY
How long to delay requesting transactions from overloaded peers (see MAX_PEER_TX_REQUEST_IN_FLIGHT).
Definition: txdownloadman.h:36
bool AddAnnouncer(const Wtxid &wtxid, NodeId peer)
Add an additional announcer to an orphan if it exists.
Definition: txorphanage.cpp:55
unsigned int TotalOrphanUsage() const
Get the total usage (weight) of all orphans.
Definition: txorphanage.h:98
static constexpr int32_t MAX_PEER_TX_REQUEST_IN_FLIGHT
Maximum number of in-flight transaction requests from a peer.
Definition: txdownloadman.h:25
static GenTxid Wtxid(const uint256 &hash)
Definition: transaction.h:435
void insert(Span< const unsigned char > vKey)
Definition: bloom.cpp:195
bool AddTxAnnouncement(NodeId peer, const GenTxid &gtxid, std::chrono::microseconds now)
Consider adding this tx hash to txrequest.
size_t Count(NodeId peer) const
Count how many announcements a peer has (REQUESTED, CANDIDATE, and COMPLETED combined).
Definition: txrequest.cpp:731
assert(!tx.IsCoinBase())
static constexpr auto TXID_RELAY_DELAY
How long to delay requesting transactions via txids, if we have wtxid-relaying peers.
Definition: txdownloadman.h:32
uint256 GetPackageHash(const std::vector< CTransactionRef > &transactions)
Get the hash of the concatenated wtxids of transactions, with wtxids treated as a little-endian numbe...
Definition: packages.cpp:151
void ConnectedPeer(NodeId nodeid, const TxDownloadConnectionInfo &info)
Creates a new PeerInfo.
std::pair< bool, std::optional< PackageToValidate > > ReceivedTx(NodeId nodeid, const CTransactionRef &ptx)
bool MaybeAddOrphanResolutionCandidate(const std::vector< Txid > &unique_parents, const Wtxid &wtxid, NodeId nodeid, std::chrono::microseconds now)
If this peer is an orphan resolution candidate for this transaction, treat the unique_parents as anno...
bool exists(const GenTxid &gtxid) const
Definition: txmempool.h:647
void GetCandidatePeers(const uint256 &txhash, std::vector< NodeId > &result_peers) const
For some txhash (txid or wtxid), finds all peers with non-COMPLETED announcements and appends them to...
Definition: txrequest.cpp:733
std::vector< GenTxid > GetRequestable(NodeId peer, std::chrono::microseconds now, std::vector< std::pair< NodeId, GenTxid >> *expired=nullptr)
Find the txids to request now from peer.
Definition: txrequest.cpp:757
void ReceivedInv(NodeId peer, const GenTxid &gtxid, bool preferred, std::chrono::microseconds reqtime)
Adds a new CANDIDATE announcement.
Definition: txrequest.cpp:741
std::optional< PackageToValidate > Find1P1CPackage(const CTransactionRef &ptx, NodeId nodeid)
Look for a child of this transaction in the orphanage to form a 1-parent-1-child package, skipping any combinations that have already been tried.
size_t CountInFlight(NodeId peer) const
Count how many REQUESTED announcements a peer has.
Definition: txrequest.cpp:729
CRollingBloomFilter & RecentConfirmedTransactionsFilter()
TxRequestTracker m_txrequest
Tracks candidates for requesting and downloading transaction data.
TxOrphanage m_orphanage
Manages unvalidated tx data (orphan transactions for which we are downloading ancestors).
CTransactionRef GetTxToReconsider(NodeId nodeid)
Returns next orphan tx to consider, or nullptr if none exist.
std::vector< CTransactionRef > Package
A package is an ordered list of transactions.
Definition: packages.h:50
transaction was missing some of its inputs
void MempoolAcceptedTx(const CTransactionRef &tx)
Respond to successful transaction submission to mempool.
RejectedTxTodo MempoolRejectedTx(const CTransactionRef &ptx, const TxValidationState &state, NodeId nodeid, bool first_time_failure)
void BlockConnected(const std::shared_ptr< const CBlock > &pblock)
void MempoolRejectedPackage(const Package &package)
std::vector< CTransactionRef > GetChildrenFromSamePeer(const CTransactionRef &parent, NodeId nodeid) const
Get all children that spend from this tx and were received from nodeid.
inputs (covered by txid) failed policy rules
void AddChildrenToWorkSet(const CTransaction &tx, FastRandomContext &rng)
Add any orphans that list a particular tx as a parent into the from peer&#39;s work set.
bool AddTxAnnouncement(NodeId peer, const GenTxid &gtxid, std::chrono::microseconds now)
Consider adding this tx hash to txrequest.
size_t Size() const
Count how many announcements are being tracked in total across all peers and transaction hashes...
Definition: txrequest.cpp:732
const CTxMemPool & m_mempool
Read-only reference to mempool.
Definition: txdownloadman.h:41
const std::vector< CTxIn > vin
Definition: transaction.h:306
bool HaveMoreWork(NodeId nodeid) const
Whether there are any orphans to reconsider for this peer.
void ReceivedNotFound(NodeId nodeid, const std::vector< uint256 > &txhashes)
Should be called when a notfound for a tx has been received.
std::pair< bool, std::optional< PackageToValidate > > ReceivedTx(NodeId nodeid, const CTransactionRef &ptx)
Marks a tx as ReceivedResponse in txrequest and checks whether AlreadyHaveTx.
RejectedTxTodo MempoolRejectedTx(const CTransactionRef &ptx, const TxValidationState &state, NodeId nodeid, bool first_time_failure)
Respond to transaction rejected from mempool.
FastRandomContext & m_rng
RNG provided by caller.
Definition: txdownloadman.h:43
const bool m_wtxid_relay
Whether this peer supports wtxid relay.
Definition: txdownloadman.h:55
const std::unique_ptr< TxDownloadManagerImpl > m_impl
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS
Maximum number of transactions to consider for requesting, per peer.
Definition: txdownloadman.h:30
CTransactionRef GetTx(const Wtxid &wtxid) const
void DisconnectedPeer(NodeId peer)
Deletes all announcements for a given peer.
Definition: txrequest.cpp:728
unsigned int UsageByPeer(NodeId peer) const
Total usage (weight) of orphans for which this peer is an announcer.
Definition: txorphanage.h:103
std::vector< Txid > GetUniqueParents(const CTransaction &tx)
Helper for getting deduplicated vector of Txids in vin.
void LimitOrphans(unsigned int max_orphans, FastRandomContext &rng)
Limit the orphanage to the given maximum.
void ReceivedNotFound(NodeId nodeid, const std::vector< uint256 > &txhashes)
Marks a tx as ReceivedResponse in txrequest.
void EraseForPeer(NodeId peer)
Maybe erase all orphans announced by a peer (eg, after that peer disconnects).
CRollingBloomFilter & RecentRejectsFilter()
std::vector< TxOrphanage::OrphanTxBase > GetOrphanTransactions() const
Wrapper for TxOrphanage::GetOrphanTransactions.
An input of a transaction.
Definition: transaction.h:66
std::map< NodeId, PeerInfo > m_peer_info
Information for all of the peers we may download transactions from.
static constexpr auto GETDATA_TX_INTERVAL
How long to wait before downloading a transaction from an additional peer.
Definition: txdownloadman.h:38
TxDownloadManager(const TxDownloadOptions &options)
CRollingBloomFilter & RecentRejectsReconsiderableFilter()
Txid hash
Definition: transaction.h:31
std::string ToString() const
Result GetResult() const
Definition: validation.h:109
int64_t NodeId
Definition: net.h:97
void RequestedTx(NodeId peer, const uint256 &txhash, std::chrono::microseconds expiry)
Marks a transaction as requested, with a specified expiry.
Definition: txrequest.cpp:747
std::string ToString() const
Definition: uint256.cpp:47
bool HaveTxFromPeer(const Wtxid &wtxid, NodeId peer) const
Check if a {tx, peer} exists in the orphanage.
bool m_should_add_extra_compact_tx
Definition: txdownloadman.h:94
fails some policy, but might be acceptable if submitted in a (different) package
const uint32_t m_max_orphan_txs
Maximum number of transactions allowed in orphanage.
Definition: txdownloadman.h:45
#define Assume(val)
Assume is the identity function.
Definition: check.h:97
bool IsWtxid() const
Definition: transaction.h:436
bool HaveTxToReconsider(NodeId peer)
Does this peer have any work to do?
bool AddTx(const CTransactionRef &tx, NodeId peer)
Add a new orphan transaction.
Definition: txorphanage.cpp:15
Definition: messages.h:20
Transaction is missing a witness.
std::vector< GenTxid > GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time)
Get getdata requests to send.
std::vector< OrphanTxBase > GetOrphanTransactions() const
256-bit opaque blob.
Definition: uint256.h:201
void DisconnectedPeer(NodeId nodeid)
Deletes all txrequest announcements and orphans for a given peer.
std::vector< GenTxid > GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time)
Get getdata requests to send.
static constexpr auto NONPREF_PEER_TX_DELAY
How long to delay requesting transactions from non-preferred peers.
Definition: txdownloadman.h:34
#define LogDebug(category,...)
Definition: logging.h:381
static transaction_identifier FromUint256(const uint256 &id)
uint32_t m_num_wtxid_peers
Number of wtxid relay peers we have in m_peer_info.
void CheckIsEmpty() const
Check that all data structures are empty.
void MempoolAcceptedTx(const CTransactionRef &tx)
CTransactionRef GetTxToReconsider(NodeId nodeid)
size_t Size() const
Return how many entries exist in the orphange.
Definition: txorphanage.h:76
The basic transaction that is broadcasted on the network and contained in blocks. ...
Definition: transaction.h:295
void BlockConnected(const std::shared_ptr< const CBlock > &pblock)
void MempoolRejectedPackage(const Package &package)
Respond to package rejected from mempool.
std::vector< TxOrphanage::OrphanTxBase > GetOrphanTransactions() const
COutPoint prevout
Definition: transaction.h:69
void ConnectedPeer(NodeId nodeid, const TxDownloadConnectionInfo &info)
void EraseForBlock(const CBlock &block)
Erase all orphans included in or invalidated by a new block.
bool AlreadyHaveTx(const GenTxid &gtxid, bool include_reconsiderable)
Check whether we already have this gtxid in:
void DisconnectedPeer(NodeId nodeid)
bool HaveTx(const Wtxid &wtxid) const
Check if we already have an orphan transaction (by wtxid only)
A generic txid reference (txid or wtxid).
Definition: transaction.h:427
static GenTxid Txid(const uint256 &hash)
Definition: transaction.h:434
void ForgetTxHash(const uint256 &txhash)
Deletes all announcements for a given txhash (both txid and wtxid ones).
Definition: txrequest.cpp:727
const uint256 & GetHash() const LIFETIMEBOUND
Definition: transaction.h:437
transaction_identifier represents the two canonical transaction identifier types (txid, wtxid).