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, p2p_inv);
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 const auto& info = it->second.m_connection_info;
209 std::vector<GenTxid> requests;
210 std::vector<std::pair<NodeId, GenTxid>> expired;
212 for (
const auto& entry : expired) {
213 LogDebug(
BCLog::NET,
"timeout of inflight %s %s from peer=%d\n", entry.second.IsWtxid() ?
"wtx" :
"tx",
214 entry.second.GetHash().ToString(), entry.first);
216 for (
const GenTxid& gtxid : requestable) {
219 gtxid.GetHash().ToString(), nodeid);
220 requests.emplace_back(gtxid);
233 for (
const auto& txhash : txhashes) {
242 const auto& parent_wtxid{ptx->GetWitnessHash()};
254 for (
const auto& child : cpfp_candidates_same_peer) {
255 Package maybe_cpfp_package{ptx, child};
275 std::vector<size_t> tx_indices(cpfp_candidates_different_peer.size());
276 std::iota(tx_indices.begin(), tx_indices.end(), 0);
277 std::shuffle(tx_indices.begin(), tx_indices.end(),
m_opts.
m_rng);
279 for (
const auto index : tx_indices) {
282 const auto [child_tx, child_sender] = cpfp_candidates_different_peer.at(index);
283 Package maybe_cpfp_package{ptx, child_tx};
309 bool add_extra_compact_tx{first_time_failure};
311 std::vector<uint256> unique_parents;
313 std::optional<node::PackageToValidate> package_to_validate;
318 if (first_time_failure && !
RecentRejectsFilter().contains(ptx->GetWitnessHash().ToUint256())) {
319 bool fRejectedParents =
false;
323 unique_parents.reserve(tx.vin.size());
324 for (
const CTxIn& txin : tx.vin) {
328 std::sort(unique_parents.begin(), unique_parents.end());
329 unique_parents.erase(std::unique(unique_parents.begin(), unique_parents.end()), unique_parents.end());
334 std::optional<uint256> rejected_parent_reconsiderable;
335 for (
const uint256& parent_txid : unique_parents) {
337 fRejectedParents =
true;
343 if (rejected_parent_reconsiderable.has_value()) {
344 fRejectedParents =
true;
347 rejected_parent_reconsiderable = parent_txid;
350 if (!fRejectedParents) {
351 const auto current_time{GetTime<std::chrono::microseconds>()};
353 for (
const uint256& parent_txid : unique_parents) {
377 unique_parents.clear();
379 tx.GetHash().ToString(),
380 tx.GetWitnessHash().ToString());
394 add_extra_compact_tx =
false;
415 if (first_time_failure) {
419 ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString());
445 LogDebug(
BCLog::TXPACKAGES,
" removed orphan tx %s (wtxid=%s)\n", ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString());
450 .m_unique_parents = std::move(unique_parents),
451 .m_package_to_validate = std::move(package_to_validate)
462 const uint256& txid = ptx->GetHash();
463 const uint256& wtxid = ptx->GetWitnessHash();
498 return {
false, std::nullopt};
509 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.
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)
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.
std::vector< std::pair< CTransactionRef, NodeId > > GetChildrenFromDifferentPeer(const CTransactionRef &parent, NodeId nodeid) const
Get all children that spend from this tx but were not received from nodeid.
size_t Size() const
Return how many entries exist in the orphange.
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.
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::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, bool p2p_inv)
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,...
CRollingBloomFilter & RecentConfirmedTransactionsFilter()
bool AddTxAnnouncement(NodeId peer, const GenTxid >xid, std::chrono::microseconds now, bool p2p_inv)
Consider adding this tx hash to txrequest.
void ReceivedNotFound(NodeId nodeid, const std::vector< uint256 > &txhashes)
Marks a tx as ReceivedResponse in txrequest.
void DisconnectedPeer(NodeId nodeid)
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.
void BlockConnected(const std::shared_ptr< const CBlock > &pblock)
CTransactionRef GetTxToReconsider(NodeId nodeid)
CRollingBloomFilter & RecentRejectsFilter()
void MempoolRejectedPackage(const Package &package)
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 these transactions' wtxids, concatenated in lexicographical order (treating the wtxid...
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.