17 const Txid& hash = tx->GetHash();
18 const Wtxid& wtxid = tx->GetWitnessHash();
39 for (
const CTxIn& txin : tx->vin) {
50 std::map<Wtxid, OrphanTx>::iterator it =
m_orphans.find(wtxid);
53 for (
const CTxIn& txin : it->second.tx->vin)
58 itPrev->second.erase(it);
59 if (itPrev->second.empty())
63 size_t old_pos = it->second.list_pos;
70 it_last->second.list_pos = old_pos;
72 const auto& txid = it->second.tx->GetHash();
88 std::map<Wtxid, OrphanTx>::iterator iter =
m_orphans.begin();
92 const auto& [wtxid, orphan] = *iter++;
93 if (orphan.fromPeer == peer) {
102 unsigned int nEvicted = 0;
103 auto nNow{Now<NodeSeconds>()};
108 std::map<Wtxid, OrphanTx>::iterator iter =
m_orphans.begin();
111 std::map<Wtxid, OrphanTx>::iterator maybeErase = iter++;
112 if (maybeErase->second.nTimeExpire <= nNow) {
113 nErased +=
EraseTx(maybeErase->second.tx->GetWitnessHash());
115 nMinExpTime = std::min(maybeErase->second.nTimeExpire, nMinExpTime);
134 for (
unsigned int i = 0; i < tx.
vout.size(); i++) {
137 for (
const auto& elem : it_by_prev->second) {
140 std::set<Wtxid>& orphan_work_set =
m_peer_work_set.try_emplace(elem->second.fromPeer).first->second;
142 orphan_work_set.insert(elem->first);
159 auto& work_set = work_set_it->second;
160 while (!work_set.empty()) {
162 work_set.erase(work_set.begin());
164 const auto orphan_it =
m_orphans.find(wtxid);
166 return orphan_it->second.tx;
177 auto& work_set = work_set_it->second;
178 return !work_set.empty();
185 std::vector<Wtxid> vOrphanErase;
191 for (
const auto& txin : tx.
vin) {
194 for (
auto mi = itByPrev->second.begin(); mi != itByPrev->second.end(); ++mi) {
202 if (vOrphanErase.size()) {
204 for (
const auto& orphanHash : vOrphanErase) {
205 nErased +=
EraseTx(orphanHash);
215 std::vector<OrphanMap::iterator> iters;
218 for (
unsigned int i = 0; i < parent->vout.size(); i++) {
221 for (
const auto& elem : it_by_prev->second) {
222 if (elem->second.fromPeer == nodeid) {
223 iters.emplace_back(elem);
232 std::sort(iters.begin(), iters.end(), [](
const auto& lhs,
const auto& rhs) {
233 if (lhs->second.nTimeExpire == rhs->second.nTimeExpire) {
234 return &(*lhs) < &(*rhs);
236 return lhs->second.nTimeExpire > rhs->second.nTimeExpire;
240 iters.erase(std::unique(iters.begin(), iters.end()), iters.end());
243 std::vector<CTransactionRef> children_found;
244 children_found.reserve(iters.size());
245 for (
const auto& child_iter : iters) {
246 children_found.emplace_back(child_iter->second.tx);
248 return children_found;
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.fromPeer != nodeid) {
262 iters.emplace_back(elem);
270 iters.erase(std::unique(iters.begin(), iters.end()), iters.end());
273 std::vector<std::pair<CTransactionRef, NodeId>> children_found;
274 children_found.reserve(iters.size());
275 for (
const auto& child_iter : iters) {
276 children_found.emplace_back(child_iter->second.tx, child_iter->second.fromPeer);
278 return children_found;
283 std::vector<OrphanTxBase>
ret;
286 ret.push_back({o.second.tx, o.second.fromPeer, o.second.nTimeExpire});
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)
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< 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.
std::vector< OrphanMap::iterator > m_orphan_list
Orphan transactions in vector for quick random eviction.
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.
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.