28 m_impl->BlockConnected(pblock);
32 m_impl->BlockDisconnected();
36 m_impl->ConnectedPeer(nodeid, info);
40 m_impl->DisconnectedPeer(nodeid);
44 return m_impl->AddTxAnnouncement(peer, gtxid, now);
48 return m_impl->GetRequestsToSend(nodeid, current_time);
52 m_impl->ReceivedNotFound(nodeid, gtxids);
56 m_impl->MempoolAcceptedTx(tx);
60 return m_impl->MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
64 m_impl->MempoolRejectedPackage(package);
68 return m_impl->ReceivedTx(nodeid, ptx);
72 return m_impl->HaveMoreWork(nodeid);
76 return m_impl->GetTxToReconsider(nodeid);
84 m_impl->CheckIsEmpty(nodeid);
88 return m_impl->GetOrphanTransactions();
102 for (
const auto& ptx : pblock->vtx) {
104 if (ptx->HasWitness()) {
176 if (
const auto* wtxid = std::get_if<Wtxid>(>xid)) {
179 std::erase_if(unique_parents, [&](
const auto& txid) {
185 if (unique_parents.empty()) {
190 m_orphanage->AddAnnouncer(orphan_tx->GetWitnessHash(), peer);
203 const auto& info = it->second.m_connection_info;
230 if (
m_orphanage->HaveTxFromPeer(wtxid, nodeid))
return false;
233 const auto& info = peer_entry.m_connection_info;
237 if (!info.m_relay_permissions) {
245 std::chrono::seconds delay{0
s};
257 for (
const auto& parent_txid : unique_parents) {
266 std::vector<GenTxid> requests;
267 std::vector<std::pair<NodeId, GenTxid>> expired;
269 for (
const auto& [expired_nodeid, gtxid] : expired) {
270 LogDebug(
BCLog::NET,
"timeout of inflight %s %s from peer=%d\n", gtxid.IsWtxid() ?
"wtx" :
"tx",
271 gtxid.ToUint256().ToString(), expired_nodeid);
273 for (
const GenTxid& gtxid : requestable) {
276 gtxid.ToUint256().ToString(), nodeid);
277 requests.emplace_back(gtxid);
290 for (
const auto& gtxid : gtxids) {
299 const auto& parent_wtxid{ptx->GetWitnessHash()};
308 const auto cpfp_candidates_same_peer{
m_orphanage->GetChildrenFromSamePeer(ptx, nodeid)};
313 for (
const auto& child : cpfp_candidates_same_peer) {
314 Package maybe_cpfp_package{ptx, child};
337 std::vector<Txid> unique_parents;
338 unique_parents.reserve(tx.
vin.size());
344 std::sort(unique_parents.begin(), unique_parents.end());
345 unique_parents.erase(std::unique(unique_parents.begin(), unique_parents.end()), unique_parents.end());
347 return unique_parents;
355 bool add_extra_compact_tx{first_time_failure};
357 std::vector<Txid> unique_parents;
359 std::optional<node::PackageToValidate> package_to_validate;
364 if (first_time_failure && !
RecentRejectsFilter().contains(ptx->GetWitnessHash().ToUint256())) {
365 bool fRejectedParents =
false;
374 std::optional<Txid> rejected_parent_reconsiderable;
375 for (
const Txid& parent_txid : unique_parents) {
377 fRejectedParents =
true;
383 if (rejected_parent_reconsiderable.has_value()) {
384 fRejectedParents =
true;
387 rejected_parent_reconsiderable = parent_txid;
390 if (!fRejectedParents) {
394 std::erase_if(unique_parents, [&](
const auto& txid) {
397 const auto now{GetTime<std::chrono::microseconds>()};
398 const auto& wtxid = ptx->GetWitnessHash();
401 add_extra_compact_tx &= !
m_orphanage->HaveTx(wtxid);
408 std::vector<NodeId> orphan_resolution_candidates{nodeid};
412 for (
const auto& nodeid : orphan_resolution_candidates) {
422 unique_parents.clear();
424 tx.GetHash().ToString(),
425 tx.GetWitnessHash().ToString());
439 add_extra_compact_tx =
false;
460 if (first_time_failure) {
464 ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString());
490 LogDebug(
BCLog::TXPACKAGES,
" removed orphan tx %s (wtxid=%s)\n", ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString());
495 .m_unique_parents = std::move(unique_parents),
496 .m_package_to_validate = std::move(package_to_validate)
507 const Txid& txid = ptx->GetHash();
508 const Wtxid& wtxid = ptx->GetWitnessHash();
543 return {
false, std::nullopt};
554 return {
true, std::nullopt};
#define Assume(val)
Assume is the identity function.
bool contains(std::span< const unsigned char > vKey) const
void insert(std::span< const unsigned char > vKey)
The basic transaction that is broadcasted on the network and contained in blocks.
const std::vector< CTxIn > vin
An input of a transaction.
bool exists(const Txid &txid) const
const uint256 & ToUint256() const LIFETIMEBOUND
void ReceivedInv(NodeId peer, const GenTxid >xid, bool preferred, std::chrono::microseconds reqtime)
Adds a new CANDIDATE announcement.
size_t CountInFlight(NodeId peer) const
Count how many REQUESTED announcements a peer has.
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...
void DisconnectedPeer(NodeId peer)
Deletes all announcements for a given peer.
void ReceivedResponse(NodeId peer, const uint256 &txhash)
Converts a CANDIDATE or REQUESTED announcement to a COMPLETED one.
void RequestedTx(NodeId peer, const uint256 &txhash, std::chrono::microseconds expiry)
Marks a transaction as requested, with a specified expiry.
size_t Count(NodeId peer) const
Count how many announcements a peer has (REQUESTED, CANDIDATE, and COMPLETED combined).
size_t Size() const
Count how many announcements are being tracked in total across all peers and transaction hashes.
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.
void ForgetTxHash(const uint256 &txhash)
Deletes all announcements for a given txhash (both txid and wtxid ones).
const std::unique_ptr< TxDownloadManagerImpl > m_impl
std::vector< GenTxid > GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time)
Get getdata requests to send.
void ReceivedNotFound(NodeId nodeid, const std::vector< GenTxid > >xids)
Should be called when a notfound for a tx has been received.
std::vector< TxOrphanage::OrphanInfo > GetOrphanTransactions() const
Wrapper for TxOrphanage::GetOrphanTransactions.
std::pair< bool, std::optional< PackageToValidate > > ReceivedTx(NodeId nodeid, const CTransactionRef &ptx)
Marks a tx as ReceivedResponse in txrequest and checks whether AlreadyHaveTx.
bool AddTxAnnouncement(NodeId peer, const GenTxid >xid, std::chrono::microseconds now)
Consider adding this tx hash to txrequest.
void BlockConnected(const std::shared_ptr< const CBlock > &pblock)
CTransactionRef GetTxToReconsider(NodeId nodeid)
Returns next orphan tx to consider, or nullptr if none exist.
void CheckIsEmpty() const
Check that all data structures are empty.
void MempoolAcceptedTx(const CTransactionRef &tx)
Respond to successful transaction submission to mempool.
void ConnectedPeer(NodeId nodeid, const TxDownloadConnectionInfo &info)
Creates a new PeerInfo.
void MempoolRejectedPackage(const Package &package)
Respond to package rejected from mempool.
void DisconnectedPeer(NodeId nodeid)
Deletes all txrequest announcements and orphans for a given peer.
RejectedTxTodo MempoolRejectedTx(const CTransactionRef &ptx, const TxValidationState &state, NodeId nodeid, bool first_time_failure)
Respond to transaction rejected from mempool.
TxDownloadManager(const TxDownloadOptions &options)
bool HaveMoreWork(NodeId nodeid) const
Whether there are any orphans to reconsider for this peer.
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,...
bool AddTxAnnouncement(NodeId peer, const GenTxid >xid, std::chrono::microseconds now)
Consider adding this tx hash to txrequest.
CRollingBloomFilter & RecentConfirmedTransactionsFilter()
std::unique_ptr< TxOrphanage > m_orphanage
Manages unvalidated tx data (orphan transactions for which we are downloading ancestors).
void DisconnectedPeer(NodeId nodeid)
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...
void ReceivedNotFound(NodeId nodeid, const std::vector< GenTxid > >xids)
Marks a tx as ReceivedResponse in txrequest.
bool HaveMoreWork(NodeId nodeid)
TxRequestTracker m_txrequest
Tracks candidates for requesting and downloading transaction data.
std::pair< bool, std::optional< PackageToValidate > > ReceivedTx(NodeId nodeid, const CTransactionRef &ptx)
void MempoolAcceptedTx(const CTransactionRef &tx)
CRollingBloomFilter & RecentRejectsReconsiderableFilter()
RejectedTxTodo MempoolRejectedTx(const CTransactionRef &ptx, const TxValidationState &state, NodeId nodeid, bool first_time_failure)
uint32_t m_num_wtxid_peers
Number of wtxid relay peers we have in m_peer_info.
void ConnectedPeer(NodeId nodeid, const TxDownloadConnectionInfo &info)
bool AlreadyHaveTx(const GenTxid >xid, bool include_reconsiderable)
Check whether we already have this gtxid in:
std::map< NodeId, PeerInfo > m_peer_info
Information for all of the peers we may download transactions from.
std::vector< TxOrphanage::OrphanInfo > GetOrphanTransactions() const
std::vector< GenTxid > GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time)
Get getdata requests to send.
std::vector< Txid > GetUniqueParents(const CTransaction &tx)
Helper for getting deduplicated vector of Txids in vin.
void BlockConnected(const std::shared_ptr< const CBlock > &pblock)
CTransactionRef GetTxToReconsider(NodeId nodeid)
CRollingBloomFilter & RecentRejectsFilter()
void MempoolRejectedPackage(const Package &package)
transaction_identifier represents the two canonical transaction identifier types (txid,...
std::string ToString() const
const uint256 & ToUint256() const LIFETIMEBOUND
static transaction_identifier FromUint256(const uint256 &id)
@ TX_MISSING_INPUTS
transaction was missing some of its inputs
@ TX_INPUTS_NOT_STANDARD
inputs (covered by txid) failed policy rules
@ TX_WITNESS_STRIPPED
Transaction is missing a witness.
@ TX_RECONSIDERABLE
fails some policy, but might be acceptable if submitted in a (different) package
#define LogDebug(category,...)
static constexpr auto GETDATA_TX_INTERVAL
How long to wait before downloading a transaction from an additional peer.
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS
Maximum number of transactions to consider for requesting, per peer.
static constexpr int32_t MAX_PEER_TX_REQUEST_IN_FLIGHT
Maximum number of in-flight transaction requests from a peer.
static constexpr auto TXID_RELAY_DELAY
How long to delay requesting transactions via txids, if we have wtxid-relaying peers.
static constexpr auto OVERLOADED_PEER_TX_DELAY
How long to delay requesting transactions from overloaded peers (see MAX_PEER_TX_REQUEST_IN_FLIGHT).
static constexpr auto NONPREF_PEER_TX_DELAY
How long to delay requesting transactions from non-preferred peers.
uint256 GetPackageHash(const std::vector< CTransactionRef > &transactions)
Get the hash of the concatenated wtxids of transactions, with wtxids treated as a little-endian numbe...
std::vector< CTransactionRef > Package
A package is an ordered list of transactions.
std::shared_ptr< const CTransaction > CTransactionRef
bool m_should_add_extra_compact_tx
const bool m_wtxid_relay
Whether this peer supports wtxid relay.
FastRandomContext & m_rng
RNG provided by caller.
const CTxMemPool & m_mempool
Read-only reference to mempool.