aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/txmempool.cpp42
-rw-r--r--src/txmempool.h12
-rw-r--r--src/validation.cpp21
3 files changed, 46 insertions, 29 deletions
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 39434e4bb6..3ad93342c4 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -156,9 +156,9 @@ bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, setEntr
// 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++) {
- txiter piter = mapTx.find(tx.vin[i].prevout.hash);
- if (piter != mapTx.end()) {
- parentHashes.insert(piter);
+ boost::optional<txiter> piter = GetIter(tx.vin[i].prevout.hash);
+ if (piter) {
+ parentHashes.insert(*piter);
if (parentHashes.size() + 1 > limitAncestorCount) {
errString = strprintf("too many unconfirmed parents [limit: %u]", limitAncestorCount);
return false;
@@ -364,12 +364,10 @@ void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, setEntries &setAnces
// Update transaction for any feeDelta created by PrioritiseTransaction
// TODO: refactor so that the fee delta is calculated before inserting
// into mapTx.
- std::map<uint256, CAmount>::const_iterator pos = mapDeltas.find(entry.GetTx().GetHash());
- if (pos != mapDeltas.end()) {
- const CAmount &delta = pos->second;
- if (delta) {
+ CAmount delta{0};
+ ApplyDelta(entry.GetTx().GetHash(), delta);
+ if (delta) {
mapTx.modify(newit, update_fee_delta(delta));
- }
}
// Update cachedInnerUsage to include contained transaction's usage.
@@ -391,11 +389,8 @@ void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, setEntries &setAnces
// to clean up the mess we're leaving here.
// Update ancestors with information about this tx
- for (const uint256 &phash : setParentTransactions) {
- txiter pit = mapTx.find(phash);
- if (pit != mapTx.end()) {
+ for (const auto& pit : GetIterSet(setParentTransactions)) {
UpdateParent(newit, pit, true);
- }
}
UpdateAncestorsOf(true, newit, setAncestors);
UpdateEntryForAncestors(newit, setAncestors);
@@ -864,6 +859,29 @@ void CTxMemPool::ClearPrioritisation(const uint256 hash)
mapDeltas.erase(hash);
}
+const CTransaction* CTxMemPool::GetConflictTx(const COutPoint& prevout) const
+{
+ const auto it = mapNextTx.find(prevout);
+ return it == mapNextTx.end() ? nullptr : it->second;
+}
+
+boost::optional<CTxMemPool::txiter> CTxMemPool::GetIter(const uint256& txid) const
+{
+ auto it = mapTx.find(txid);
+ if (it != mapTx.end()) return it;
+ return boost::optional<txiter>{};
+}
+
+CTxMemPool::setEntries CTxMemPool::GetIterSet(const std::set<uint256>& hashes) const
+{
+ CTxMemPool::setEntries ret;
+ for (const auto& h : hashes) {
+ const auto mi = GetIter(h);
+ if (mi) ret.insert(*mi);
+ }
+ return ret;
+}
+
bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const
{
for (unsigned int i = 0; i < tx.vin.size(); i++)
diff --git a/src/txmempool.h b/src/txmempool.h
index 2163b5eb21..913501fd66 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -566,7 +566,15 @@ public:
void ApplyDelta(const uint256 hash, CAmount &nFeeDelta) const;
void ClearPrioritisation(const uint256 hash);
-public:
+ /** Get the transaction in the pool that spends the same prevout */
+ const CTransaction* GetConflictTx(const COutPoint& prevout) const EXCLUSIVE_LOCKS_REQUIRED(cs);
+
+ /** Returns an iterator to the given hash, if found */
+ boost::optional<txiter> GetIter(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs);
+
+ /** Translate a set of hashes into a set of pool iterators to avoid repeated lookups */
+ setEntries GetIterSet(const std::set<uint256>& hashes) const EXCLUSIVE_LOCKS_REQUIRED(cs);
+
/** Remove a set of transactions from the mempool.
* If a transaction is in this set, then all in-mempool descendants must
* also be in the set, unless this transaction is being removed for being
@@ -639,7 +647,7 @@ public:
return totalTxSize;
}
- bool exists(uint256 hash) const
+ bool exists(const uint256& hash) const
{
LOCK(cs);
return (mapTx.count(hash) != 0);
diff --git a/src/validation.cpp b/src/validation.cpp
index 7ec0c6a961..2ad2422618 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -602,10 +602,8 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
std::set<uint256> setConflicts;
for (const CTxIn &txin : tx.vin)
{
- auto itConflicting = pool.mapNextTx.find(txin.prevout);
- if (itConflicting != pool.mapNextTx.end())
- {
- const CTransaction *ptxConflicting = itConflicting->second;
+ const CTransaction* ptxConflicting = pool.GetConflictTx(txin.prevout);
+ if (ptxConflicting) {
if (!setConflicts.count(ptxConflicting->GetHash()))
{
// Allow opt-out of transaction replacement by setting
@@ -786,16 +784,8 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
CFeeRate newFeeRate(nModifiedFees, nSize);
std::set<uint256> setConflictsParents;
const int maxDescendantsToVisit = 100;
- CTxMemPool::setEntries setIterConflicting;
- for (const uint256 &hashConflicting : setConflicts)
- {
- CTxMemPool::txiter mi = pool.mapTx.find(hashConflicting);
- if (mi == pool.mapTx.end())
- continue;
-
- // Save these to avoid repeated lookups
- setIterConflicting.insert(mi);
-
+ const CTxMemPool::setEntries setIterConflicting = pool.GetIterSet(setConflicts);
+ for (const auto& mi : setIterConflicting) {
// Don't allow the replacement to reduce the feerate of the
// mempool.
//
@@ -861,11 +851,12 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
// Rather than check the UTXO set - potentially expensive -
// it's cheaper to just check if the new input refers to a
// tx that's in the mempool.
- if (pool.mapTx.find(tx.vin[j].prevout.hash) != pool.mapTx.end())
+ if (pool.exists(tx.vin[j].prevout.hash)) {
return state.DoS(0, false,
REJECT_NONSTANDARD, "replacement-adds-unconfirmed", false,
strprintf("replacement %s adds unconfirmed input, idx %d",
hash.ToString(), j));
+ }
}
}