diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp index 7a01633592..f07f06f88f 100644 --- a/src/rpc/mempool.cpp +++ b/src/rpc/mempool.cpp @@ -327,7 +327,7 @@ static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPool info.pushKV("depends", std::move(depends)); UniValue spent(UniValue::VARR); - for (const CTxMemPoolEntry& child : e.GetMemPoolChildrenConst()) { + for (const CTxMemPoolEntry& child : pool.GetChildren(e)) { spent.push_back(child.GetTx().GetHash().ToString()); } diff --git a/src/test/fuzz/package_eval.cpp b/src/test/fuzz/package_eval.cpp index 50f4c416d7..3f1eeeb3dd 100644 --- a/src/test/fuzz/package_eval.cpp +++ b/src/test/fuzz/package_eval.cpp @@ -174,7 +174,7 @@ std::optional GetChildEvictingPrevout(const CTxMemPool& tx_pool) const auto& entry = *Assert(tx_pool.GetEntry(tx_info.tx->GetHash())); std::vector dust_indexes{GetDust(*tx_info.tx, tx_pool.m_opts.dust_relay_feerate)}; if (!dust_indexes.empty()) { - const auto& children = entry.GetMemPoolChildrenConst(); + const auto& children = tx_pool.GetChildren(entry); if (!children.empty()) { Assert(children.size() == 1); // Find an input that doesn't spend from parent's txid diff --git a/src/test/util/txmempool.cpp b/src/test/util/txmempool.cpp index ffa21a4188..e85c496d01 100644 --- a/src/test/util/txmempool.cpp +++ b/src/test/util/txmempool.cpp @@ -157,7 +157,7 @@ void CheckMempoolEphemeralInvariants(const CTxMemPool& tx_pool) Assert(entry.GetFee() == 0 && entry.GetModifiedFee() == 0); // Transaction has single dust; make sure it's swept or will not be mined - const auto& children = entry.GetMemPoolChildrenConst(); + const auto& children = tx_pool.GetChildren(entry); // Multiple children should never happen as non-dust-spending child // can get mined as package @@ -199,12 +199,12 @@ void CheckMempoolTRUCInvariants(const CTxMemPool& tx_pool) if (anc_count > 1) { Assert(entry.GetTxSize() <= TRUC_CHILD_MAX_VSIZE); // All TRUC transactions must only have TRUC unconfirmed parents. - const auto& parents = entry.GetMemPoolParentsConst(); + const auto& parents = tx_pool.GetParents(entry); Assert(parents.begin()->get().GetSharedTx()->version == TRUC_VERSION); } } else if (anc_count > 1) { // All non-TRUC transactions must only have non-TRUC unconfirmed parents. - for (const auto& parent : entry.GetMemPoolParentsConst()) { + for (const auto& parent : tx_pool.GetParents(entry)) { Assert(parent.get().GetSharedTx()->version != TRUC_VERSION); } } diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 8ba41e9403..fb835b1f3a 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -54,6 +54,38 @@ bool TestLockPointValidity(CChain& active_chain, const LockPoints& lp) return true; } +std::vector CTxMemPool::GetChildren(const CTxMemPoolEntry& entry) const +{ + LOCK(cs); + std::vector ret; + setEntries children; + auto iter = mapNextTx.lower_bound(COutPoint(entry.GetTx().GetHash(), 0)); + for (; iter != mapNextTx.end() && iter->first->hash == entry.GetTx().GetHash(); ++iter) { + children.insert(iter->second); + } + for (const auto& child : children) { + ret.emplace_back(*child); + } + return ret; +} + +std::vector CTxMemPool::GetParents(const CTxMemPoolEntry& entry) const +{ + LOCK(cs); + std::vector ret; + std::set inputs; + for (const auto& txin : entry.GetTx().vin) { + inputs.insert(txin.prevout.hash); + } + for (const auto& hash : inputs) { + std::optional piter = GetIter(hash); + if (piter) { + ret.emplace_back(**piter); + } + } + return ret; +} + void CTxMemPool::UpdateTransactionsFromBlock(const std::vector& vHashesToUpdate) { AssertLockHeld(cs); diff --git a/src/txmempool.h b/src/txmempool.h index 3c4882154c..addf3e137b 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -289,6 +289,8 @@ public: int64_t GetDescendantCount(txiter it) const { LOCK(cs); return m_txgraph->GetDescendants(*it, TxGraph::Level::MAIN).size(); } int64_t GetDescendantCount(const CTxMemPoolEntry &e) const { LOCK(cs); return m_txgraph->GetDescendants(e, TxGraph::Level::MAIN).size(); } int64_t GetAncestorCount(const CTxMemPoolEntry &e) const { LOCK(cs); return m_txgraph->GetAncestors(e, TxGraph::Level::MAIN).size(); } + std::vector GetChildren(const CTxMemPoolEntry &entry) const; + std::vector GetParents(const CTxMemPoolEntry &entry) const; private: typedef std::map cacheMap;