Skip to content

Commit e0a4f9d

Browse files
committed
Merge #13793: tx pool: Use class methods to hide raw map iterator impl details
faa1a74 tx pool: Use class methods to hide raw map iterator impl details (MarcoFalke) Pull request description: ATMP et al would often use map iterator implementation details such as `end()` or `find()`, which is acceptable in current code. However, this not only makes it impossible to turn the maps into private members in the future but also makes it harder to replace the maps with different data structures. This is required for and split off of #13804 Tree-SHA512: 4f9017fd1d98d9df49d25bba92655a4a97755eea161fd1cbb565ceb81bbc2b4924129d214f8a29563a77e3d8eef85a67c81245ecdc9a9e5292d419922a93cb88
2 parents 838b85e + faa1a74 commit e0a4f9d

File tree

3 files changed

+46
-29
lines changed

3 files changed

+46
-29
lines changed

src/txmempool.cpp

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,9 @@ bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, setEntr
156156
// GetMemPoolParents() is only valid for entries in the mempool, so we
157157
// iterate mapTx to find parents.
158158
for (unsigned int i = 0; i < tx.vin.size(); i++) {
159-
txiter piter = mapTx.find(tx.vin[i].prevout.hash);
160-
if (piter != mapTx.end()) {
161-
parentHashes.insert(piter);
159+
boost::optional<txiter> piter = GetIter(tx.vin[i].prevout.hash);
160+
if (piter) {
161+
parentHashes.insert(*piter);
162162
if (parentHashes.size() + 1 > limitAncestorCount) {
163163
errString = strprintf("too many unconfirmed parents [limit: %u]", limitAncestorCount);
164164
return false;
@@ -364,12 +364,10 @@ void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, setEntries &setAnces
364364
// Update transaction for any feeDelta created by PrioritiseTransaction
365365
// TODO: refactor so that the fee delta is calculated before inserting
366366
// into mapTx.
367-
std::map<uint256, CAmount>::const_iterator pos = mapDeltas.find(entry.GetTx().GetHash());
368-
if (pos != mapDeltas.end()) {
369-
const CAmount &delta = pos->second;
370-
if (delta) {
367+
CAmount delta{0};
368+
ApplyDelta(entry.GetTx().GetHash(), delta);
369+
if (delta) {
371370
mapTx.modify(newit, update_fee_delta(delta));
372-
}
373371
}
374372

375373
// Update cachedInnerUsage to include contained transaction's usage.
@@ -391,11 +389,8 @@ void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, setEntries &setAnces
391389
// to clean up the mess we're leaving here.
392390

393391
// Update ancestors with information about this tx
394-
for (const uint256 &phash : setParentTransactions) {
395-
txiter pit = mapTx.find(phash);
396-
if (pit != mapTx.end()) {
392+
for (const auto& pit : GetIterSet(setParentTransactions)) {
397393
UpdateParent(newit, pit, true);
398-
}
399394
}
400395
UpdateAncestorsOf(true, newit, setAncestors);
401396
UpdateEntryForAncestors(newit, setAncestors);
@@ -864,6 +859,29 @@ void CTxMemPool::ClearPrioritisation(const uint256 hash)
864859
mapDeltas.erase(hash);
865860
}
866861

862+
const CTransaction* CTxMemPool::GetConflictTx(const COutPoint& prevout) const
863+
{
864+
const auto it = mapNextTx.find(prevout);
865+
return it == mapNextTx.end() ? nullptr : it->second;
866+
}
867+
868+
boost::optional<CTxMemPool::txiter> CTxMemPool::GetIter(const uint256& txid) const
869+
{
870+
auto it = mapTx.find(txid);
871+
if (it != mapTx.end()) return it;
872+
return boost::optional<txiter>{};
873+
}
874+
875+
CTxMemPool::setEntries CTxMemPool::GetIterSet(const std::set<uint256>& hashes) const
876+
{
877+
CTxMemPool::setEntries ret;
878+
for (const auto& h : hashes) {
879+
const auto mi = GetIter(h);
880+
if (mi) ret.insert(*mi);
881+
}
882+
return ret;
883+
}
884+
867885
bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const
868886
{
869887
for (unsigned int i = 0; i < tx.vin.size(); i++)

src/txmempool.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,15 @@ class CTxMemPool
566566
void ApplyDelta(const uint256 hash, CAmount &nFeeDelta) const;
567567
void ClearPrioritisation(const uint256 hash);
568568

569-
public:
569+
/** Get the transaction in the pool that spends the same prevout */
570+
const CTransaction* GetConflictTx(const COutPoint& prevout) const EXCLUSIVE_LOCKS_REQUIRED(cs);
571+
572+
/** Returns an iterator to the given hash, if found */
573+
boost::optional<txiter> GetIter(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs);
574+
575+
/** Translate a set of hashes into a set of pool iterators to avoid repeated lookups */
576+
setEntries GetIterSet(const std::set<uint256>& hashes) const EXCLUSIVE_LOCKS_REQUIRED(cs);
577+
570578
/** Remove a set of transactions from the mempool.
571579
* If a transaction is in this set, then all in-mempool descendants must
572580
* also be in the set, unless this transaction is being removed for being
@@ -639,7 +647,7 @@ class CTxMemPool
639647
return totalTxSize;
640648
}
641649

642-
bool exists(uint256 hash) const
650+
bool exists(const uint256& hash) const
643651
{
644652
LOCK(cs);
645653
return (mapTx.count(hash) != 0);

src/validation.cpp

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -602,10 +602,8 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
602602
std::set<uint256> setConflicts;
603603
for (const CTxIn &txin : tx.vin)
604604
{
605-
auto itConflicting = pool.mapNextTx.find(txin.prevout);
606-
if (itConflicting != pool.mapNextTx.end())
607-
{
608-
const CTransaction *ptxConflicting = itConflicting->second;
605+
const CTransaction* ptxConflicting = pool.GetConflictTx(txin.prevout);
606+
if (ptxConflicting) {
609607
if (!setConflicts.count(ptxConflicting->GetHash()))
610608
{
611609
// Allow opt-out of transaction replacement by setting
@@ -786,16 +784,8 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
786784
CFeeRate newFeeRate(nModifiedFees, nSize);
787785
std::set<uint256> setConflictsParents;
788786
const int maxDescendantsToVisit = 100;
789-
CTxMemPool::setEntries setIterConflicting;
790-
for (const uint256 &hashConflicting : setConflicts)
791-
{
792-
CTxMemPool::txiter mi = pool.mapTx.find(hashConflicting);
793-
if (mi == pool.mapTx.end())
794-
continue;
795-
796-
// Save these to avoid repeated lookups
797-
setIterConflicting.insert(mi);
798-
787+
const CTxMemPool::setEntries setIterConflicting = pool.GetIterSet(setConflicts);
788+
for (const auto& mi : setIterConflicting) {
799789
// Don't allow the replacement to reduce the feerate of the
800790
// mempool.
801791
//
@@ -861,11 +851,12 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
861851
// Rather than check the UTXO set - potentially expensive -
862852
// it's cheaper to just check if the new input refers to a
863853
// tx that's in the mempool.
864-
if (pool.mapTx.find(tx.vin[j].prevout.hash) != pool.mapTx.end())
854+
if (pool.exists(tx.vin[j].prevout.hash)) {
865855
return state.DoS(0, false,
866856
REJECT_NONSTANDARD, "replacement-adds-unconfirmed", false,
867857
strprintf("replacement %s adds unconfirmed input, idx %d",
868858
hash.ToString(), j));
859+
}
869860
}
870861
}
871862

0 commit comments

Comments
 (0)