mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-06-22 14:52:41 +02:00
Merge #13793: tx pool: Use class methods to hide raw map iterator impl details
faa1a749428a195af784633eb78e1df5d6a0e875 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:
commit
e0a4f9de7f
@ -156,9 +156,9 @@ bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, setEntr
|
|||||||
// GetMemPoolParents() is only valid for entries in the mempool, so we
|
// GetMemPoolParents() is only valid for entries in the mempool, so we
|
||||||
// iterate mapTx to find parents.
|
// iterate mapTx to find parents.
|
||||||
for (unsigned int i = 0; i < tx.vin.size(); i++) {
|
for (unsigned int i = 0; i < tx.vin.size(); i++) {
|
||||||
txiter piter = mapTx.find(tx.vin[i].prevout.hash);
|
boost::optional<txiter> piter = GetIter(tx.vin[i].prevout.hash);
|
||||||
if (piter != mapTx.end()) {
|
if (piter) {
|
||||||
parentHashes.insert(piter);
|
parentHashes.insert(*piter);
|
||||||
if (parentHashes.size() + 1 > limitAncestorCount) {
|
if (parentHashes.size() + 1 > limitAncestorCount) {
|
||||||
errString = strprintf("too many unconfirmed parents [limit: %u]", limitAncestorCount);
|
errString = strprintf("too many unconfirmed parents [limit: %u]", limitAncestorCount);
|
||||||
return false;
|
return false;
|
||||||
@ -364,12 +364,10 @@ void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, setEntries &setAnces
|
|||||||
// Update transaction for any feeDelta created by PrioritiseTransaction
|
// Update transaction for any feeDelta created by PrioritiseTransaction
|
||||||
// TODO: refactor so that the fee delta is calculated before inserting
|
// TODO: refactor so that the fee delta is calculated before inserting
|
||||||
// into mapTx.
|
// into mapTx.
|
||||||
std::map<uint256, CAmount>::const_iterator pos = mapDeltas.find(entry.GetTx().GetHash());
|
CAmount delta{0};
|
||||||
if (pos != mapDeltas.end()) {
|
ApplyDelta(entry.GetTx().GetHash(), delta);
|
||||||
const CAmount &delta = pos->second;
|
if (delta) {
|
||||||
if (delta) {
|
|
||||||
mapTx.modify(newit, update_fee_delta(delta));
|
mapTx.modify(newit, update_fee_delta(delta));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update cachedInnerUsage to include contained transaction's usage.
|
// 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.
|
// to clean up the mess we're leaving here.
|
||||||
|
|
||||||
// Update ancestors with information about this tx
|
// Update ancestors with information about this tx
|
||||||
for (const uint256 &phash : setParentTransactions) {
|
for (const auto& pit : GetIterSet(setParentTransactions)) {
|
||||||
txiter pit = mapTx.find(phash);
|
|
||||||
if (pit != mapTx.end()) {
|
|
||||||
UpdateParent(newit, pit, true);
|
UpdateParent(newit, pit, true);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
UpdateAncestorsOf(true, newit, setAncestors);
|
UpdateAncestorsOf(true, newit, setAncestors);
|
||||||
UpdateEntryForAncestors(newit, setAncestors);
|
UpdateEntryForAncestors(newit, setAncestors);
|
||||||
@ -864,6 +859,29 @@ void CTxMemPool::ClearPrioritisation(const uint256 hash)
|
|||||||
mapDeltas.erase(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
|
bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
||||||
|
@ -566,7 +566,15 @@ public:
|
|||||||
void ApplyDelta(const uint256 hash, CAmount &nFeeDelta) const;
|
void ApplyDelta(const uint256 hash, CAmount &nFeeDelta) const;
|
||||||
void ClearPrioritisation(const uint256 hash);
|
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.
|
/** Remove a set of transactions from the mempool.
|
||||||
* If a transaction is in this set, then all in-mempool descendants must
|
* 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
|
* also be in the set, unless this transaction is being removed for being
|
||||||
@ -639,7 +647,7 @@ public:
|
|||||||
return totalTxSize;
|
return totalTxSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool exists(uint256 hash) const
|
bool exists(const uint256& hash) const
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
return (mapTx.count(hash) != 0);
|
return (mapTx.count(hash) != 0);
|
||||||
|
@ -602,10 +602,8 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
|
|||||||
std::set<uint256> setConflicts;
|
std::set<uint256> setConflicts;
|
||||||
for (const CTxIn &txin : tx.vin)
|
for (const CTxIn &txin : tx.vin)
|
||||||
{
|
{
|
||||||
auto itConflicting = pool.mapNextTx.find(txin.prevout);
|
const CTransaction* ptxConflicting = pool.GetConflictTx(txin.prevout);
|
||||||
if (itConflicting != pool.mapNextTx.end())
|
if (ptxConflicting) {
|
||||||
{
|
|
||||||
const CTransaction *ptxConflicting = itConflicting->second;
|
|
||||||
if (!setConflicts.count(ptxConflicting->GetHash()))
|
if (!setConflicts.count(ptxConflicting->GetHash()))
|
||||||
{
|
{
|
||||||
// Allow opt-out of transaction replacement by setting
|
// Allow opt-out of transaction replacement by setting
|
||||||
@ -786,16 +784,8 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
|
|||||||
CFeeRate newFeeRate(nModifiedFees, nSize);
|
CFeeRate newFeeRate(nModifiedFees, nSize);
|
||||||
std::set<uint256> setConflictsParents;
|
std::set<uint256> setConflictsParents;
|
||||||
const int maxDescendantsToVisit = 100;
|
const int maxDescendantsToVisit = 100;
|
||||||
CTxMemPool::setEntries setIterConflicting;
|
const CTxMemPool::setEntries setIterConflicting = pool.GetIterSet(setConflicts);
|
||||||
for (const uint256 &hashConflicting : setConflicts)
|
for (const auto& mi : setIterConflicting) {
|
||||||
{
|
|
||||||
CTxMemPool::txiter mi = pool.mapTx.find(hashConflicting);
|
|
||||||
if (mi == pool.mapTx.end())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Save these to avoid repeated lookups
|
|
||||||
setIterConflicting.insert(mi);
|
|
||||||
|
|
||||||
// Don't allow the replacement to reduce the feerate of the
|
// Don't allow the replacement to reduce the feerate of the
|
||||||
// mempool.
|
// mempool.
|
||||||
//
|
//
|
||||||
@ -861,11 +851,12 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
|
|||||||
// Rather than check the UTXO set - potentially expensive -
|
// Rather than check the UTXO set - potentially expensive -
|
||||||
// it's cheaper to just check if the new input refers to a
|
// it's cheaper to just check if the new input refers to a
|
||||||
// tx that's in the mempool.
|
// 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,
|
return state.DoS(0, false,
|
||||||
REJECT_NONSTANDARD, "replacement-adds-unconfirmed", false,
|
REJECT_NONSTANDARD, "replacement-adds-unconfirmed", false,
|
||||||
strprintf("replacement %s adds unconfirmed input, idx %d",
|
strprintf("replacement %s adds unconfirmed input, idx %d",
|
||||||
hash.ToString(), j));
|
hash.ToString(), j));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user