mempool: use util::Result for CalculateAncestorsAndCheckLimits

Avoid using setAncestors outparameter, simplify function signatures
and avoid creating unused dummy strings.
This commit is contained in:
stickies-v 2022-10-07 17:38:04 +01:00
parent 85892f77c9
commit 66e028f739
No known key found for this signature in database
GPG Key ID: 5CB1CE6E5E66A757
2 changed files with 36 additions and 38 deletions

View File

@ -17,8 +17,10 @@
#include <util/check.h>
#include <util/moneystr.h>
#include <util/overflow.h>
#include <util/result.h>
#include <util/system.h>
#include <util/time.h>
#include <util/translation.h>
#include <validationinterface.h>
#include <cmath>
@ -147,32 +149,29 @@ void CTxMemPool::UpdateTransactionsFromBlock(const std::vector<uint256>& vHashes
}
}
bool CTxMemPool::CalculateAncestorsAndCheckLimits(size_t entry_size,
size_t entry_count,
setEntries& setAncestors,
CTxMemPoolEntry::Parents& staged_ancestors,
const Limits& limits,
std::string &errString) const
util::Result<CTxMemPool::setEntries> CTxMemPool::CalculateAncestorsAndCheckLimits(
size_t entry_size,
size_t entry_count,
CTxMemPoolEntry::Parents& staged_ancestors,
const Limits& limits) const
{
size_t totalSizeWithAncestors = entry_size;
setEntries ancestors;
while (!staged_ancestors.empty()) {
const CTxMemPoolEntry& stage = staged_ancestors.begin()->get();
txiter stageit = mapTx.iterator_to(stage);
setAncestors.insert(stageit);
ancestors.insert(stageit);
staged_ancestors.erase(stage);
totalSizeWithAncestors += stageit->GetTxSize();
if (stageit->GetSizeWithDescendants() + entry_size > static_cast<uint64_t>(limits.descendant_size_vbytes)) {
errString = strprintf("exceeds descendant size limit for tx %s [limit: %u]", stageit->GetTx().GetHash().ToString(), limits.descendant_size_vbytes);
return false;
return util::Error{Untranslated(strprintf("exceeds descendant size limit for tx %s [limit: %u]", stageit->GetTx().GetHash().ToString(), limits.descendant_size_vbytes))};
} else if (stageit->GetCountWithDescendants() + entry_count > static_cast<uint64_t>(limits.descendant_count)) {
errString = strprintf("too many descendants for tx %s [limit: %u]", stageit->GetTx().GetHash().ToString(), limits.descendant_count);
return false;
return util::Error{Untranslated(strprintf("too many descendants for tx %s [limit: %u]", stageit->GetTx().GetHash().ToString(), limits.descendant_count))};
} else if (totalSizeWithAncestors > static_cast<uint64_t>(limits.ancestor_size_vbytes)) {
errString = strprintf("exceeds ancestor size limit [limit: %u]", limits.ancestor_size_vbytes);
return false;
return util::Error{Untranslated(strprintf("exceeds ancestor size limit [limit: %u]", limits.ancestor_size_vbytes))};
}
const CTxMemPoolEntry::Parents& parents = stageit->GetMemPoolParentsConst();
@ -180,17 +179,16 @@ bool CTxMemPool::CalculateAncestorsAndCheckLimits(size_t entry_size,
txiter parent_it = mapTx.iterator_to(parent);
// If this is a new ancestor, add it.
if (setAncestors.count(parent_it) == 0) {
if (ancestors.count(parent_it) == 0) {
staged_ancestors.insert(parent);
}
if (staged_ancestors.size() + setAncestors.size() + entry_count > static_cast<uint64_t>(limits.ancestor_count)) {
errString = strprintf("too many unconfirmed ancestors [limit: %u]", limits.ancestor_count);
return false;
if (staged_ancestors.size() + ancestors.size() + entry_count > static_cast<uint64_t>(limits.ancestor_count)) {
return util::Error{Untranslated(strprintf("too many unconfirmed ancestors [limit: %u]", limits.ancestor_count))};
}
}
}
return true;
return ancestors;
}
bool CTxMemPool::CheckPackageLimits(const Package& package,
@ -215,13 +213,11 @@ bool CTxMemPool::CheckPackageLimits(const Package& package,
// When multiple transactions are passed in, the ancestors and descendants of all transactions
// considered together must be within limits even if they are not interdependent. This may be
// stricter than the limits for each individual transaction.
setEntries setAncestors;
const auto ret = CalculateAncestorsAndCheckLimits(total_size, package.size(),
setAncestors, staged_ancestors,
limits, errString);
const auto ancestors{CalculateAncestorsAndCheckLimits(total_size, package.size(),
staged_ancestors, limits)};
// It's possible to overestimate the ancestor/descendant totals.
if (!ret) errString.insert(0, "possibly ");
return ret;
if (!ancestors.has_value()) errString = "possibly " + util::ErrorString(ancestors).original;
return ancestors.has_value();
}
bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry,
@ -254,9 +250,14 @@ bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry,
staged_ancestors = it->GetMemPoolParentsConst();
}
return CalculateAncestorsAndCheckLimits(entry.GetTxSize(), /*entry_count=*/1,
setAncestors, staged_ancestors,
limits, errString);
const auto calculated_ancestors{CalculateAncestorsAndCheckLimits(entry.GetTxSize(), /*entry_count=*/1,
staged_ancestors, limits)};
if (!calculated_ancestors.has_value()) {
errString = util::ErrorString(calculated_ancestors).original;
return false;
}
setAncestors = *calculated_ancestors;
return true;
}
void CTxMemPool::UpdateAncestorsOf(bool add, txiter it, setEntries &setAncestors)

View File

@ -28,6 +28,7 @@
#include <txmempool_entry.h>
#include <util/epochguard.h>
#include <util/hasher.h>
#include <util/result.h>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
@ -428,24 +429,20 @@ private:
/**
* Helper function to calculate all in-mempool ancestors of staged_ancestors and apply ancestor
* and descendant limits (including staged_ancestors thsemselves, entry_size and entry_count).
* and descendant limits (including staged_ancestors themselves, entry_size and entry_count).
*
* @param[in] entry_size Virtual size to include in the limits.
* @param[in] entry_count How many entries to include in the limits.
* @param[out] setAncestors Will be populated with all mempool ancestors.
* @param[in] staged_ancestors Should contain entries in the mempool.
* @param[in] limits Maximum number and size of ancestors and descendants
* @param[out] errString Populated with error reason if any limits are hit
*
* @return true if no limits were hit and all in-mempool ancestors were calculated, false
* otherwise
* @return all in-mempool ancestors, or an error if any ancestor or descendant limits were hit
*/
bool CalculateAncestorsAndCheckLimits(size_t entry_size,
size_t entry_count,
setEntries& setAncestors,
CTxMemPoolEntry::Parents &staged_ancestors,
const Limits& limits,
std::string &errString) const EXCLUSIVE_LOCKS_REQUIRED(cs);
util::Result<setEntries> CalculateAncestorsAndCheckLimits(size_t entry_size,
size_t entry_count,
CTxMemPoolEntry::Parents &staged_ancestors,
const Limits& limits
) const EXCLUSIVE_LOCKS_REQUIRED(cs);
public:
indirectmap<COutPoint, const CTransaction*> mapNextTx GUARDED_BY(cs);