Skip to content

Commit c6e016a

Browse files
committed
[mempool] check ancestor/descendant limits for packages
When calculating ancestor/descendant counts for transactions in the package, as a heuristic, count every transaction in the package as an ancestor and descendant of every other transaction in the package. This may overestimate, but will not underestimate, the ancestor/descendant counts. This shortcut still produces an accurate count for packages of 1 parent + 1 child.
1 parent f551841 commit c6e016a

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

src/txmempool.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,41 @@ bool CTxMemPool::CalculateAncestorsAndCheckLimits(size_t entry_size,
200200
return true;
201201
}
202202

203+
bool CTxMemPool::CheckPackageLimits(const Package& package,
204+
uint64_t limitAncestorCount,
205+
uint64_t limitAncestorSize,
206+
uint64_t limitDescendantCount,
207+
uint64_t limitDescendantSize,
208+
std::string &errString) const
209+
{
210+
CTxMemPoolEntry::Parents staged_ancestors;
211+
size_t total_size = 0;
212+
for (const auto& tx : package) {
213+
total_size += GetVirtualTransactionSize(*tx);
214+
for (const auto& input : tx->vin) {
215+
std::optional<txiter> piter = GetIter(input.prevout.hash);
216+
if (piter) {
217+
staged_ancestors.insert(**piter);
218+
if (staged_ancestors.size() + package.size() > limitAncestorCount) {
219+
errString = strprintf("too many unconfirmed parents [limit: %u]", limitAncestorCount);
220+
return false;
221+
}
222+
}
223+
}
224+
}
225+
// When multiple transactions are passed in, the ancestors and descendants of all transactions
226+
// considered together must be within limits even if they are not interdependent. This may be
227+
// stricter than the limits for each individual transaction.
228+
setEntries setAncestors;
229+
const auto ret = CalculateAncestorsAndCheckLimits(total_size, package.size(),
230+
setAncestors, staged_ancestors,
231+
limitAncestorCount, limitAncestorSize,
232+
limitDescendantCount, limitDescendantSize, errString);
233+
// It's possible to overestimate the ancestor/descendant totals.
234+
if (!ret) errString.insert(0, "possibly ");
235+
return ret;
236+
}
237+
203238
bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry,
204239
setEntries &setAncestors,
205240
uint64_t limitAncestorCount,

src/txmempool.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <coins.h>
1919
#include <indirectmap.h>
2020
#include <policy/feerate.h>
21+
#include <policy/packages.h>
2122
#include <primitives/transaction.h>
2223
#include <random.h>
2324
#include <sync.h>
@@ -700,6 +701,28 @@ class CTxMemPool
700701
*/
701702
bool CalculateMemPoolAncestors(const CTxMemPoolEntry& entry, setEntries& setAncestors, uint64_t limitAncestorCount, uint64_t limitAncestorSize, uint64_t limitDescendantCount, uint64_t limitDescendantSize, std::string& errString, bool fSearchForParents = true) const EXCLUSIVE_LOCKS_REQUIRED(cs);
702703

704+
/** Calculate all in-mempool ancestors of a set of transactions not already in the mempool and
705+
* check ancestor and descendant limits. Heuristics are used to estimate the ancestor and
706+
* descendant count of all entries if the package were to be added to the mempool. The limits
707+
* are applied to the union of all package transactions. For example, if the package has 3
708+
* transactions and limitAncestorCount = 25, the union of all 3 sets of ancestors (including the
709+
* transactions themselves) must be <= 22.
710+
* @param[in] package Transaction package being evaluated for acceptance
711+
* to mempool. The transactions need not be direct
712+
* ancestors/descendants of each other.
713+
* @param[in] limitAncestorCount Max number of txns including ancestors.
714+
* @param[in] limitAncestorSize Max virtual size including ancestors.
715+
* @param[in] limitDescendantCount Max number of txns including descendants.
716+
* @param[in] limitDescendantSize Max virtual size including descendants.
717+
* @param[out] errString Populated with error reason if a limit is hit.
718+
*/
719+
bool CheckPackageLimits(const Package& package,
720+
uint64_t limitAncestorCount,
721+
uint64_t limitAncestorSize,
722+
uint64_t limitDescendantCount,
723+
uint64_t limitDescendantSize,
724+
std::string &errString) const EXCLUSIVE_LOCKS_REQUIRED(cs);
725+
703726
/** Populate setDescendants with all in-mempool descendants of hash.
704727
* Assumes that setDescendants includes all in-mempool descendants of anything
705728
* already in it. */

0 commit comments

Comments
 (0)