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()) {
185 std::erase_if(unique_parents, [&](
const auto& txid){
191 if (unique_parents.empty()) {
209 const auto& info = it->second.m_connection_info;
239 const auto& info = peer_entry.m_connection_info;
243 if (!info.m_relay_permissions) {
251 std::chrono::seconds delay{0
s};
263 for (
const auto& parent_txid : unique_parents) {
272 std::vector<GenTxid> requests;
273 std::vector<std::pair<NodeId, GenTxid>> 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);
279 for (
const GenTxid& gtxid : requestable) {
282 gtxid.GetHash().ToString(), nodeid);
283 requests.emplace_back(gtxid);
296 for (
const auto& txhash : txhashes) {
305 const auto& parent_wtxid{ptx->GetWitnessHash()};
319 for (
const auto& child : cpfp_candidates_same_peer) {
320 Package maybe_cpfp_package{ptx, child};
343 std::vector<Txid> unique_parents;
344 unique_parents.reserve(tx.
vin.size());
350 std::sort(unique_parents.begin(), unique_parents.end());
351 unique_parents.erase(std::unique(unique_parents.begin(), unique_parents.end()), unique_parents.end());
353 return unique_parents;
361 bool add_extra_compact_tx{first_time_failure};
363 std::vector<Txid> unique_parents;
365 std::optional<node::PackageToValidate> package_to_validate;
370 if (first_time_failure && !
RecentRejectsFilter().contains(ptx->GetWitnessHash().ToUint256())) {
371 bool fRejectedParents =
false;
380 std::optional<uint256> rejected_parent_reconsiderable;
381 for (
const uint256& parent_txid : unique_parents) {
383 fRejectedParents =
true;
389 if (rejected_parent_reconsiderable.has_value()) {
390 fRejectedParents =
true;
393 rejected_parent_reconsiderable = parent_txid;
396 if (!fRejectedParents) {
400 std::erase_if(unique_parents, [&](
const auto& txid){
403 const auto now{GetTime<std::chrono::microseconds>()};
404 const auto& wtxid = ptx->GetWitnessHash();
414 std::vector<NodeId> orphan_resolution_candidates{nodeid};
418 for (
const auto& nodeid : orphan_resolution_candidates) {
433 unique_parents.clear();
435 tx.GetHash().ToString(),
436 tx.GetWitnessHash().ToString());
450 add_extra_compact_tx =
false;
471 if (first_time_failure) {
475 ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString());
501 LogDebug(
BCLog::TXPACKAGES,
" removed orphan tx %s (wtxid=%s)\n", ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString());
506 .m_unique_parents = std::move(unique_parents),
507 .m_package_to_validate = std::move(package_to_validate)
518 const uint256& txid = ptx->GetHash();
519 const uint256& wtxid = ptx->GetWitnessHash();
554 return {
false, std::nullopt};
565 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).
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.
void AddChildrenToWorkSet(const CTransaction &tx, FastRandomContext &rng)
Add any orphans that list a particular tx as a parent into the from peer's work set.
bool HaveTx(const Wtxid &wtxid) const
Check if we already have an orphan transaction (by wtxid only)
unsigned int UsageByPeer(NodeId peer) const
Total usage (weight) of orphans for which this peer is an announcer.
bool HaveTxToReconsider(NodeId peer)
Does this peer have any work to do?
unsigned int TotalOrphanUsage() const
Get the total usage (weight) of all orphans.
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 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).
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)
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 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,...
std::string ToString() const
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.