diff --git a/src/policy/rbf.cpp b/src/policy/rbf.cpp index fdf6f53cf40..c78fed8ef3e 100644 --- a/src/policy/rbf.cpp +++ b/src/policy/rbf.cpp @@ -39,7 +39,7 @@ RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool) // If all the inputs have nSequence >= maxint-1, it still might be // signaled for RBF if any unconfirmed parents have signaled. const auto& entry{*Assert(pool.GetEntry(tx.GetHash()))}; - auto ancestors{pool.CalculateMemPoolAncestors(entry, /*fSearchForParents=*/false)}; + auto ancestors{pool.CalculateMemPoolAncestors(entry)}; for (CTxMemPool::txiter it : ancestors) { if (SignalsOptInRBF(it->GetTx())) { diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp index 01870ef3577..7a016335926 100644 --- a/src/rpc/mempool.cpp +++ b/src/rpc/mempool.cpp @@ -474,7 +474,7 @@ static RPCHelpMan getmempoolancestors() throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool"); } - auto ancestors{mempool.CalculateMemPoolAncestors(*entry, /*fSearchForParents=*/false)}; + auto ancestors{mempool.CalculateMemPoolAncestors(*entry)}; if (!fVerbose) { UniValue o(UniValue::VARR); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index f83b4544f40..2b8bec25498 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -99,31 +99,6 @@ void CTxMemPool::UpdateTransactionsFromBlock(const std::vector& vHashesToU } } -CTxMemPool::setEntries CTxMemPool::CalculateAncestors(CTxMemPoolEntry::Parents& staged_ancestors) const -{ - setEntries ancestors; - - while (!staged_ancestors.empty()) { - const CTxMemPoolEntry& stage = staged_ancestors.begin()->get(); - txiter stageit = mapTx.iterator_to(stage); - - ancestors.insert(stageit); - staged_ancestors.erase(stage); - - const CTxMemPoolEntry::Parents& parents = stageit->GetMemPoolParentsConst(); - for (const CTxMemPoolEntry& parent : parents) { - txiter parent_it = mapTx.iterator_to(parent); - - // If this is a new ancestor, add it. - if (ancestors.count(parent_it) == 0) { - staged_ancestors.insert(parent); - } - } - } - - return ancestors; -} - util::Result CTxMemPool::CheckPackageLimits(const Package& package, const int64_t total_vsize) const { @@ -138,31 +113,42 @@ bool CTxMemPool::HasDescendants(const Txid& txid) const return m_txgraph->GetDescendants(*entry, TxGraph::Level::MAIN).size() > 1; } -CTxMemPool::setEntries CTxMemPool::CalculateMemPoolAncestors( - const CTxMemPoolEntry &entry, - bool fSearchForParents /* = true */) const +CTxMemPool::setEntries CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry) const { - CTxMemPoolEntry::Parents staged_ancestors; - const CTransaction &tx = entry.GetTx(); - - if (fSearchForParents) { - // Get parents of this transaction that are in the mempool - // GetMemPoolParents() is only valid for entries in the mempool, so we - // iterate mapTx to find parents. - for (unsigned int i = 0; i < tx.vin.size(); i++) { - std::optional piter = GetIter(tx.vin[i].prevout.hash); - if (piter) { - staged_ancestors.insert(**piter); + auto ancestors = m_txgraph->GetAncestors(entry, TxGraph::Level::MAIN); + setEntries ret; + if (ancestors.size() > 0) { + for (auto ancestor : ancestors) { + if (ancestor != &entry) { + ret.insert(mapTx.iterator_to(static_cast(*ancestor))); } } - } else { - // If we're not searching for parents, we require this to already be an - // entry in the mempool and use the entry's cached parents. - txiter it = mapTx.iterator_to(entry); - staged_ancestors = it->GetMemPoolParentsConst(); + return ret; } - return CalculateAncestors(staged_ancestors); + // If we didn't get anything back, the transaction is not in the graph. + // Find each parent and call GetAncestors on each. + setEntries staged_parents; + const CTransaction &tx = entry.GetTx(); + + // Get parents of this transaction that are in the mempool + // GetMemPoolParents() is only valid for entries in the mempool, so we + // iterate mapTx to find parents. + for (unsigned int i = 0; i < tx.vin.size(); i++) { + std::optional piter = GetIter(tx.vin[i].prevout.hash); + if (piter) { + staged_parents.insert(*piter); + } + } + + for (const auto& parent : staged_parents) { + auto parent_ancestors = m_txgraph->GetAncestors(*parent, TxGraph::Level::MAIN); + for (auto ancestor : parent_ancestors) { + ret.insert(mapTx.iterator_to(static_cast(*ancestor))); + } + } + + return ret; } void CTxMemPool::UpdateAncestorsOf(bool add, txiter it) diff --git a/src/txmempool.h b/src/txmempool.h index d2b7f232b94..3c4882154cd 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -304,17 +304,6 @@ private: */ std::set m_unbroadcast_txids GUARDED_BY(cs); - - /** - * Helper function to calculate all in-mempool ancestors of staged_ancestors - * - * @param[in] staged_ancestors Should contain entries in the mempool. - * - * @return all in-mempool ancestors - */ - setEntries CalculateAncestors(CTxMemPoolEntry::Parents &staged_ancestors) - const EXCLUSIVE_LOCKS_REQUIRED(cs); - static TxMempoolInfo GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it) { return TxMempoolInfo{it->GetSharedTx(), it->GetTime(), it->GetFee(), it->GetTxSize(), it->GetModifiedFee() - it->GetFee()}; @@ -429,18 +418,13 @@ public: } /** - * Calculate all in-mempool ancestors of entry. - * (these are all calculated including the tx itself) + * Calculate all in-mempool ancestors of entry (not including the tx itself) * * @param[in] entry CTxMemPoolEntry of which all in-mempool ancestors are calculated - * @param[in] fSearchForParents Whether to search a tx's vin for in-mempool parents, or look - * up parents from mapLinks. Must be true for entries not in - * the mempool * * @return all in-mempool ancestors */ - setEntries CalculateMemPoolAncestors(const CTxMemPoolEntry& entry, - bool fSearchForParents = true) const EXCLUSIVE_LOCKS_REQUIRED(cs); + setEntries CalculateMemPoolAncestors(const CTxMemPoolEntry& entry) const EXCLUSIVE_LOCKS_REQUIRED(cs); bool HasDescendants(const Txid& txid) const;