17 const Txid& hash = tx->GetHash();
18 const Wtxid& wtxid = tx->GetWitnessHash();
42 for (
const CTxIn& txin : tx->vin) {
55 Assume(!it->second.announcers.empty());
56 const auto ret = it->second.announcers.insert(peer);
67 std::map<Wtxid, OrphanTx>::iterator it =
m_orphans.find(wtxid);
70 for (
const CTxIn& txin : it->second.tx->vin)
75 itPrev->second.erase(it);
76 if (itPrev->second.empty())
80 size_t old_pos = it->second.list_pos;
87 it_last->second.list_pos = old_pos;
89 const auto& txid = it->second.tx->GetHash();
105 std::map<Wtxid, OrphanTx>::iterator iter =
m_orphans.begin();
109 auto& [wtxid, orphan] = *iter++;
110 auto orphan_it = orphan.announcers.find(peer);
111 if (orphan_it != orphan.announcers.end()) {
112 orphan.announcers.erase(peer);
115 if (orphan.announcers.empty()) {
116 nErased +=
EraseTx(orphan.tx->GetWitnessHash());
125 unsigned int nEvicted = 0;
126 auto nNow{Now<NodeSeconds>()};
131 std::map<Wtxid, OrphanTx>::iterator iter =
m_orphans.begin();
134 std::map<Wtxid, OrphanTx>::iterator maybeErase = iter++;
135 if (maybeErase->second.nTimeExpire <= nNow) {
136 nErased +=
EraseTx(maybeErase->first);
138 nMinExpTime = std::min(maybeErase->second.nTimeExpire, nMinExpTime);
157 for (
unsigned int i = 0; i < tx.
vout.size(); i++) {
160 for (
const auto& elem : it_by_prev->second) {
162 if (!
Assume(!elem->second.announcers.empty()))
continue;
163 for (
const auto announcer: elem->second.announcers) {
166 std::set<Wtxid>& orphan_work_set =
m_peer_work_set.try_emplace(announcer).first->second;
168 orphan_work_set.insert(elem->first);
185 return it !=
m_orphans.end() ? it->second.tx :
nullptr;
191 return (it !=
m_orphans.end() && it->second.announcers.contains(peer));
198 auto& work_set = work_set_it->second;
199 while (!work_set.empty()) {
201 work_set.erase(work_set.begin());
203 const auto orphan_it =
m_orphans.find(wtxid);
205 return orphan_it->second.tx;
216 auto& work_set = work_set_it->second;
217 return !work_set.empty();
224 std::vector<Wtxid> vOrphanErase;
230 for (
const auto& txin : tx.
vin) {
233 for (
auto mi = itByPrev->second.begin(); mi != itByPrev->second.end(); ++mi) {
241 if (vOrphanErase.size()) {
243 for (
const auto& orphanHash : vOrphanErase) {
244 nErased +=
EraseTx(orphanHash);
254 std::vector<OrphanMap::iterator> iters;
257 for (
unsigned int i = 0; i < parent->vout.size(); i++) {
260 for (
const auto& elem : it_by_prev->second) {
261 if (elem->second.announcers.contains(nodeid)) {
262 iters.emplace_back(elem);
271 std::sort(iters.begin(), iters.end(), [](
const auto& lhs,
const auto& rhs) {
272 if (lhs->second.nTimeExpire == rhs->second.nTimeExpire) {
273 return &(*lhs) < &(*rhs);
275 return lhs->second.nTimeExpire > rhs->second.nTimeExpire;
279 iters.erase(std::unique(iters.begin(), iters.end()), iters.end());
282 std::vector<CTransactionRef> children_found;
283 children_found.reserve(iters.size());
284 for (
const auto& child_iter : iters) {
285 children_found.emplace_back(child_iter->second.tx);
287 return children_found;
292 std::vector<OrphanTxBase>
ret;
295 ret.push_back({o.second.tx, o.second.announcers, o.second.nTimeExpire});
#define Assume(val)
Assume is the identity function.
std::vector< CTransactionRef > vtx
An outpoint - a combination of a transaction hash and an index n into its vout.
The basic transaction that is broadcasted on the network and contained in blocks.
const std::vector< CTxOut > vout
const Wtxid & GetWitnessHash() const LIFETIMEBOUND
const Txid & GetHash() const LIFETIMEBOUND
const std::vector< CTxIn > vin
An input of a transaction.
I randrange(I range) noexcept
Generate a random integer in the range [0..range), with range > 0.
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.
std::map< NodeId, std::set< Wtxid > > m_peer_work_set
Which peer provided the orphans that need to be reconsidered.
std::map< COutPoint, std::set< OrphanMap::iterator, IteratorComparator > > m_outpoint_to_orphan_it
Index from the parents' COutPoint into the m_orphans.
std::vector< OrphanMap::iterator > m_orphan_list
Orphan transactions in vector for quick random eviction.
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.
std::map< Wtxid, OrphanTx > m_orphans
Map from wtxid to orphan transaction record.
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.
NodeSeconds m_next_sweep
Timestamp for the next scheduled sweep of expired orphans.
bool HaveTxFromPeer(const Wtxid &wtxid, NodeId peer) const
Check if a {tx, peer} exists in the orphanage.
std::string ToString() const
constexpr const std::byte * begin() const
static int32_t GetTransactionWeight(const CTransaction &tx)
#define LogDebug(category,...)
static constexpr int32_t MAX_STANDARD_TX_WEIGHT
The maximum weight for transactions we're willing to relay/mine.
std::shared_ptr< const CTransaction > CTransactionRef
static time_point now() noexcept
Return current system time or mocked time, if set.
static constexpr auto ORPHAN_TX_EXPIRE_TIME
Expiration time for orphan transactions.
static constexpr auto ORPHAN_TX_EXPIRE_INTERVAL
Minimum time between orphan transactions expire time checks.