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, txhashes);
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()) {
184 std::erase_if(unique_parents, [&](
const auto& txid){
188 if (unique_parents.empty())
return true;
193 const auto& info =
m_peer_info.at(peer).m_connection_info;
194 for (
const auto& parent_txid : unique_parents) {
211 const auto& info = it->second.m_connection_info;
236 if (
m_peer_info.count(nodeid) == 0)
return std::nullopt;
240 const auto& info = peer_entry.m_connection_info;
243 if (!info.m_relay_permissions) {
251 std::chrono::seconds delay{0
s};
266 std::vector<GenTxid> requests;
267 std::vector<std::pair<NodeId, GenTxid>> expired;
269 for (
const auto& entry : expired) {
270 LogDebug(
BCLog::NET,
"timeout of inflight %s %s from peer=%d\n", entry.second.IsWtxid() ?
"wtx" :
"tx",
271 entry.second.GetHash().ToString(), entry.first);
273 for (
const GenTxid& gtxid : requestable) {
276 gtxid.GetHash().ToString(), nodeid);
277 requests.emplace_back(gtxid);
290 for (
const auto& txhash : txhashes) {
299 const auto& parent_wtxid{ptx->GetWitnessHash()};
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<uint256> rejected_parent_reconsiderable;
375 for (
const uint256& 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();
403 auto add_orphan_reso_candidate = [&](
const CTransactionRef& orphan_tx,
const std::vector<Txid>& unique_parents,
NodeId nodeid, std::chrono::microseconds now) {
404 const auto& wtxid = orphan_tx->GetWitnessHash();
406 const auto& info =
m_peer_info.at(nodeid).m_connection_info;
411 for (
const auto& parent_txid : unique_parents) {
421 add_orphan_reso_candidate(ptx, unique_parents, nodeid, now);
423 add_orphan_reso_candidate(ptx, unique_parents, candidate, now);
435 unique_parents.clear();
437 tx.GetHash().ToString(),
438 tx.GetWitnessHash().ToString());
452 add_extra_compact_tx =
false;
473 if (first_time_failure) {
477 ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString());
503 LogDebug(
BCLog::TXPACKAGES,
" removed orphan tx %s (wtxid=%s)\n", ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString());
508 .m_unique_parents = std::move(unique_parents),
509 .m_package_to_validate = std::move(package_to_validate)
520 const uint256& txid = ptx->GetHash();
521 const uint256& wtxid = ptx->GetWitnessHash();
556 return {
false, std::nullopt};
567 return {
true, std::nullopt};
#define Assume(val)
Assume is the identity function.
bool contains(Span< const unsigned char > vKey) const
void insert(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 GenTxid >xid) const
A generic txid reference (txid or wtxid).
static GenTxid Wtxid(const uint256 &hash)
const uint256 & GetHash() const LIFETIMEBOUND
static GenTxid Txid(const uint256 &hash)
bool AddTx(const CTransactionRef &tx, NodeId peer)
Add a new orphan transaction.
void EraseForPeer(NodeId peer)
Maybe erase all orphans announced by a peer (eg, after that peer disconnects).
void AddChildrenToWorkSet(const CTransaction &tx)
Add any orphans that list a particular tx as a parent into the from peer's work set.
std::vector< OrphanTxBase > GetOrphanTransactions() const
void LimitOrphans(unsigned int max_orphans, FastRandomContext &rng)
Limit the orphanage to the given maximum.
int EraseTx(const Wtxid &wtxid)
Erase an orphan by wtxid.
void EraseForBlock(const CBlock &block)
Erase all orphans included in or invalidated by a new block.
size_t Size() const
Return how many entries exist in the orphange.
CTransactionRef GetTx(const Wtxid &wtxid) const
bool AddAnnouncer(const Wtxid &wtxid, NodeId peer)
Add an additional announcer to an orphan if it exists.
std::vector< CTransactionRef > GetChildrenFromSamePeer(const CTransactionRef &parent, NodeId nodeid) const
Get all children that spend from this tx and were received from nodeid.
bool HaveTx(const Wtxid &wtxid) const
Check if we already have an orphan transaction (by wtxid only)
bool HaveTxToReconsider(NodeId peer)
Does this peer have any work to do?
CTransactionRef GetTxToReconsider(NodeId peer)
Extract a transaction from a peer's work set Returns nullptr if there are no transactions to work on.
bool HaveTxFromPeer(const Wtxid &wtxid, NodeId peer) const
Check if a {tx, peer} exists in the orphanage.
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 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).
std::vector< NodeId > GetCandidatePeers(const CTransactionRef &tx) const
For some tx return all peers with non-COMPLETED announcements for its txid or wtxid.
std::string ToString() const
std::vector< TxOrphanage::OrphanTxBase > GetOrphanTransactions() const
Wrapper for TxOrphanage::GetOrphanTransactions.
const std::unique_ptr< TxDownloadManagerImpl > m_impl
std::vector< GenTxid > GetRequestsToSend(NodeId nodeid, std::chrono::microseconds current_time)
Get getdata requests to send.
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)
void ReceivedNotFound(NodeId nodeid, const std::vector< uint256 > &txhashes)
Should be called when a notfound for a tx has been received.
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()
void ReceivedNotFound(NodeId nodeid, const std::vector< uint256 > &txhashes)
Marks a tx as ReceivedResponse in txrequest.
void DisconnectedPeer(NodeId nodeid)
std::optional< std::chrono::seconds > OrphanResolutionCandidate(NodeId nodeid, const Wtxid &orphan_wtxid, size_t num_parents)
Determine candidacy (and delay) for potential orphan resolution candidate.
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)
std::vector< TxOrphanage::OrphanTxBase > GetOrphanTransactions() const
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.
TxOrphanage m_orphanage
Manages unvalidated tx data (orphan transactions for which we are downloading ancestors).
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,...
static constexpr auto size()
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 uint32_t m_max_orphan_txs
Maximum number of transactions allowed in orphanage.
const CTxMemPool & m_mempool
Read-only reference to mempool.