Merge #13793: tx pool: Use class methods to hide raw map iterator impl details

faa1a74942 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
This commit is contained in:
Wladimir J. van der Laan 2018-09-10 18:19:02 +02:00
commit e0a4f9de7f
No known key found for this signature in database
GPG key ID: 1E4AED62986CD25D
3 changed files with 46 additions and 29 deletions

View file

@ -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++)

View file

@ -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);

View file

@ -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));
}
}
}