Skip to content

Commit d33c589

Browse files
committed
Merge bitcoin/bitcoin#26103: refactor: mempool: use CTxMemPool::Limits
33b12e5 docs: improve docs where MemPoolLimits is used (stickies-v) 6945853 test: use NoLimits() in MempoolIndexingTest (stickies-v) 3a86f24 refactor: mempool: use CTxMempool::Limits (stickies-v) b85af25 refactor: mempool: add MemPoolLimits::NoLimits() (stickies-v) Pull request description: Mempool currently considers 4 limits regarding ancestor and descendant count and size, which get passed around between functions quite a bit. This PR uses `CTxMemPool::Limits` introduced in bitcoin/bitcoin#25290 to simplify those signatures and callsites. The purpose of this PR is to improve readability and maintenance, without behaviour change. As noted in the first commit "refactor: mempool: change MemPoolLimits members to uint", we currently have an underflow issue where a user could pass a negative `-limitancestorsize`, which is eventually cast to an unsigned integer. This behaviour already exists. Because it's orthogonal and to minimize scope, I think this should be fixed in a separate PR. ACKs for top commit: hebasto: ACK 33b12e5, I have reviewed the code and it looks OK, I agree it can be merged. glozow: reACK 33b12e5 Tree-SHA512: 591c6dcee1894f1c3ca28b34a680eeadcf0d40cda92451b4a422c03087b27d682b5e30ba4367abd75a99b5ccb115b7884b0026958d3c7dddab030549db5a4056
2 parents ec8016e + 33b12e5 commit d33c589

File tree

9 files changed

+93
-96
lines changed

9 files changed

+93
-96
lines changed

src/kernel/mempool_limits.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ struct MemPoolLimits {
2424
int64_t descendant_count{DEFAULT_DESCENDANT_LIMIT};
2525
//! The maximum allowed size in virtual bytes of an entry and its descendants within a package.
2626
int64_t descendant_size_vbytes{DEFAULT_DESCENDANT_SIZE_LIMIT_KVB * 1'000};
27+
28+
/**
29+
* @return MemPoolLimits with all the limits set to the maximum
30+
*/
31+
static constexpr MemPoolLimits NoLimits()
32+
{
33+
int64_t no_limit{std::numeric_limits<int64_t>::max()};
34+
return {no_limit, no_limit, no_limit, no_limit};
35+
}
2736
};
2837
} // namespace kernel
2938

src/node/interfaces.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,8 +660,7 @@ class ChainImpl : public Chain
660660
std::string unused_error_string;
661661
LOCK(m_node.mempool->cs);
662662
return m_node.mempool->CalculateMemPoolAncestors(
663-
entry, ancestors, limits.ancestor_count, limits.ancestor_size_vbytes,
664-
limits.descendant_count, limits.descendant_size_vbytes, unused_error_string);
663+
entry, ancestors, limits, unused_error_string);
665664
}
666665
CFeeRate estimateSmartFee(int num_blocks, bool conservative, FeeCalculation* calc) override
667666
{

src/node/miner.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,9 +392,8 @@ void BlockAssembler::addPackageTxs(const CTxMemPool& mempool, int& nPackagesSele
392392
}
393393

394394
CTxMemPool::setEntries ancestors;
395-
uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
396395
std::string dummy;
397-
mempool.CalculateMemPoolAncestors(*iter, ancestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false);
396+
mempool.CalculateMemPoolAncestors(*iter, ancestors, CTxMemPool::Limits::NoLimits(), dummy, false);
398397

399398
onlyUnconfirmed(ancestors);
400399
ancestors.insert(iter);

src/policy/rbf.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,9 @@ RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool)
3636

3737
// If all the inputs have nSequence >= maxint-1, it still might be
3838
// signaled for RBF if any unconfirmed parents have signaled.
39-
uint64_t noLimit = std::numeric_limits<uint64_t>::max();
4039
std::string dummy;
4140
CTxMemPoolEntry entry = *pool.mapTx.find(tx.GetHash());
42-
pool.CalculateMemPoolAncestors(entry, ancestors, noLimit, noLimit, noLimit, noLimit, dummy, false);
41+
pool.CalculateMemPoolAncestors(entry, ancestors, CTxMemPool::Limits::NoLimits(), dummy, false);
4342

4443
for (CTxMemPool::txiter it : ancestors) {
4544
if (SignalsOptInRBF(it->GetTx())) {

src/rpc/mempool.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,9 +449,8 @@ static RPCHelpMan getmempoolancestors()
449449
}
450450

451451
CTxMemPool::setEntries setAncestors;
452-
uint64_t noLimit = std::numeric_limits<uint64_t>::max();
453452
std::string dummy;
454-
mempool.CalculateMemPoolAncestors(*it, setAncestors, noLimit, noLimit, noLimit, noLimit, dummy, false);
453+
mempool.CalculateMemPoolAncestors(*it, setAncestors, CTxMemPool::Limits::NoLimits(), dummy, false);
455454

456455
if (!fVerbose) {
457456
UniValue o(UniValue::VARR);

src/test/mempool_tests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
203203

204204
CTxMemPool::setEntries setAncestorsCalculated;
205205
std::string dummy;
206-
BOOST_CHECK_EQUAL(pool.CalculateMemPoolAncestors(entry.Fee(2000000LL).FromTx(tx7), setAncestorsCalculated, 100, 1000000, 1000, 1000000, dummy), true);
206+
BOOST_CHECK_EQUAL(pool.CalculateMemPoolAncestors(entry.Fee(2'000'000LL).FromTx(tx7), setAncestorsCalculated, CTxMemPool::Limits::NoLimits(), dummy), true);
207207
BOOST_CHECK(setAncestorsCalculated == setAncestors);
208208

209209
pool.addUnchecked(entry.FromTx(tx7), setAncestors);
@@ -261,7 +261,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
261261
tx10.vout[0].nValue = 10 * COIN;
262262

263263
setAncestorsCalculated.clear();
264-
BOOST_CHECK_EQUAL(pool.CalculateMemPoolAncestors(entry.Fee(200000LL).Time(4).FromTx(tx10), setAncestorsCalculated, 100, 1000000, 1000, 1000000, dummy), true);
264+
BOOST_CHECK_EQUAL(pool.CalculateMemPoolAncestors(entry.Fee(200'000LL).Time(4).FromTx(tx10), setAncestorsCalculated, CTxMemPool::Limits::NoLimits(), dummy), true);
265265
BOOST_CHECK(setAncestorsCalculated == setAncestors);
266266

267267
pool.addUnchecked(entry.FromTx(tx10), setAncestors);

src/txmempool.cpp

Lines changed: 21 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -187,10 +187,7 @@ bool CTxMemPool::CalculateAncestorsAndCheckLimits(size_t entry_size,
187187
size_t entry_count,
188188
setEntries& setAncestors,
189189
CTxMemPoolEntry::Parents& staged_ancestors,
190-
uint64_t limitAncestorCount,
191-
uint64_t limitAncestorSize,
192-
uint64_t limitDescendantCount,
193-
uint64_t limitDescendantSize,
190+
const Limits& limits,
194191
std::string &errString) const
195192
{
196193
size_t totalSizeWithAncestors = entry_size;
@@ -203,14 +200,14 @@ bool CTxMemPool::CalculateAncestorsAndCheckLimits(size_t entry_size,
203200
staged_ancestors.erase(stage);
204201
totalSizeWithAncestors += stageit->GetTxSize();
205202

206-
if (stageit->GetSizeWithDescendants() + entry_size > limitDescendantSize) {
207-
errString = strprintf("exceeds descendant size limit for tx %s [limit: %u]", stageit->GetTx().GetHash().ToString(), limitDescendantSize);
203+
if (stageit->GetSizeWithDescendants() + entry_size > static_cast<uint64_t>(limits.descendant_size_vbytes)) {
204+
errString = strprintf("exceeds descendant size limit for tx %s [limit: %u]", stageit->GetTx().GetHash().ToString(), limits.descendant_size_vbytes);
208205
return false;
209-
} else if (stageit->GetCountWithDescendants() + entry_count > limitDescendantCount) {
210-
errString = strprintf("too many descendants for tx %s [limit: %u]", stageit->GetTx().GetHash().ToString(), limitDescendantCount);
206+
} else if (stageit->GetCountWithDescendants() + entry_count > static_cast<uint64_t>(limits.descendant_count)) {
207+
errString = strprintf("too many descendants for tx %s [limit: %u]", stageit->GetTx().GetHash().ToString(), limits.descendant_count);
211208
return false;
212-
} else if (totalSizeWithAncestors > limitAncestorSize) {
213-
errString = strprintf("exceeds ancestor size limit [limit: %u]", limitAncestorSize);
209+
} else if (totalSizeWithAncestors > static_cast<uint64_t>(limits.ancestor_size_vbytes)) {
210+
errString = strprintf("exceeds ancestor size limit [limit: %u]", limits.ancestor_size_vbytes);
214211
return false;
215212
}
216213

@@ -222,8 +219,8 @@ bool CTxMemPool::CalculateAncestorsAndCheckLimits(size_t entry_size,
222219
if (setAncestors.count(parent_it) == 0) {
223220
staged_ancestors.insert(parent);
224221
}
225-
if (staged_ancestors.size() + setAncestors.size() + entry_count > limitAncestorCount) {
226-
errString = strprintf("too many unconfirmed ancestors [limit: %u]", limitAncestorCount);
222+
if (staged_ancestors.size() + setAncestors.size() + entry_count > static_cast<uint64_t>(limits.ancestor_count)) {
223+
errString = strprintf("too many unconfirmed ancestors [limit: %u]", limits.ancestor_count);
227224
return false;
228225
}
229226
}
@@ -233,10 +230,7 @@ bool CTxMemPool::CalculateAncestorsAndCheckLimits(size_t entry_size,
233230
}
234231

235232
bool CTxMemPool::CheckPackageLimits(const Package& package,
236-
uint64_t limitAncestorCount,
237-
uint64_t limitAncestorSize,
238-
uint64_t limitDescendantCount,
239-
uint64_t limitDescendantSize,
233+
const Limits& limits,
240234
std::string &errString) const
241235
{
242236
CTxMemPoolEntry::Parents staged_ancestors;
@@ -247,8 +241,8 @@ bool CTxMemPool::CheckPackageLimits(const Package& package,
247241
std::optional<txiter> piter = GetIter(input.prevout.hash);
248242
if (piter) {
249243
staged_ancestors.insert(**piter);
250-
if (staged_ancestors.size() + package.size() > limitAncestorCount) {
251-
errString = strprintf("too many unconfirmed parents [limit: %u]", limitAncestorCount);
244+
if (staged_ancestors.size() + package.size() > static_cast<uint64_t>(limits.ancestor_count)) {
245+
errString = strprintf("too many unconfirmed parents [limit: %u]", limits.ancestor_count);
252246
return false;
253247
}
254248
}
@@ -260,19 +254,15 @@ bool CTxMemPool::CheckPackageLimits(const Package& package,
260254
setEntries setAncestors;
261255
const auto ret = CalculateAncestorsAndCheckLimits(total_size, package.size(),
262256
setAncestors, staged_ancestors,
263-
limitAncestorCount, limitAncestorSize,
264-
limitDescendantCount, limitDescendantSize, errString);
257+
limits, errString);
265258
// It's possible to overestimate the ancestor/descendant totals.
266259
if (!ret) errString.insert(0, "possibly ");
267260
return ret;
268261
}
269262

270263
bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry,
271264
setEntries &setAncestors,
272-
uint64_t limitAncestorCount,
273-
uint64_t limitAncestorSize,
274-
uint64_t limitDescendantCount,
275-
uint64_t limitDescendantSize,
265+
const Limits& limits,
276266
std::string &errString,
277267
bool fSearchForParents /* = true */) const
278268
{
@@ -287,8 +277,8 @@ bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry,
287277
std::optional<txiter> piter = GetIter(tx.vin[i].prevout.hash);
288278
if (piter) {
289279
staged_ancestors.insert(**piter);
290-
if (staged_ancestors.size() + 1 > limitAncestorCount) {
291-
errString = strprintf("too many unconfirmed parents [limit: %u]", limitAncestorCount);
280+
if (staged_ancestors.size() + 1 > static_cast<uint64_t>(limits.ancestor_count)) {
281+
errString = strprintf("too many unconfirmed parents [limit: %u]", limits.ancestor_count);
292282
return false;
293283
}
294284
}
@@ -302,8 +292,7 @@ bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry,
302292

303293
return CalculateAncestorsAndCheckLimits(entry.GetTxSize(), /*entry_count=*/1,
304294
setAncestors, staged_ancestors,
305-
limitAncestorCount, limitAncestorSize,
306-
limitDescendantCount, limitDescendantSize, errString);
295+
limits, errString);
307296
}
308297

309298
void CTxMemPool::UpdateAncestorsOf(bool add, txiter it, setEntries &setAncestors)
@@ -347,7 +336,6 @@ void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove, b
347336
{
348337
// For each entry, walk back all ancestors and decrement size associated with this
349338
// transaction
350-
const uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
351339
if (updateDescendants) {
352340
// updateDescendants should be true whenever we're not recursively
353341
// removing a tx and all its descendants, eg when a transaction is
@@ -390,7 +378,7 @@ void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove, b
390378
// mempool parents we'd calculate by searching, and it's important that
391379
// we use the cached notion of ancestor transactions as the set of
392380
// things to update for removal.
393-
CalculateMemPoolAncestors(entry, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false);
381+
CalculateMemPoolAncestors(entry, setAncestors, Limits::NoLimits(), dummy, false);
394382
// Note that UpdateAncestorsOf severs the child links that point to
395383
// removeIt in the entries for the parents of removeIt.
396384
UpdateAncestorsOf(false, removeIt, setAncestors);
@@ -744,9 +732,8 @@ void CTxMemPool::check(const CCoinsViewCache& active_coins_tip, int64_t spendhei
744732
assert(std::equal(setParentCheck.begin(), setParentCheck.end(), it->GetMemPoolParentsConst().begin(), comp));
745733
// Verify ancestor state is correct.
746734
setEntries setAncestors;
747-
uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
748735
std::string dummy;
749-
CalculateMemPoolAncestors(*it, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy);
736+
CalculateMemPoolAncestors(*it, setAncestors, Limits::NoLimits(), dummy);
750737
uint64_t nCountCheck = setAncestors.size() + 1;
751738
uint64_t nSizeCheck = it->GetTxSize();
752739
CAmount nFeesCheck = it->GetModifiedFee();
@@ -908,9 +895,8 @@ void CTxMemPool::PrioritiseTransaction(const uint256& hash, const CAmount& nFeeD
908895
mapTx.modify(it, [&nFeeDelta](CTxMemPoolEntry& e) { e.UpdateModifiedFee(nFeeDelta); });
909896
// Now update all ancestors' modified fees with descendants
910897
setEntries setAncestors;
911-
uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
912898
std::string dummy;
913-
CalculateMemPoolAncestors(*it, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false);
899+
CalculateMemPoolAncestors(*it, setAncestors, Limits::NoLimits(), dummy, false);
914900
for (txiter ancestorIt : setAncestors) {
915901
mapTx.modify(ancestorIt, [=](CTxMemPoolEntry& e){ e.UpdateDescendantState(0, nFeeDelta, 0);});
916902
}
@@ -1049,9 +1035,8 @@ int CTxMemPool::Expire(std::chrono::seconds time)
10491035
void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, bool validFeeEstimate)
10501036
{
10511037
setEntries setAncestors;
1052-
uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
10531038
std::string dummy;
1054-
CalculateMemPoolAncestors(entry, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy);
1039+
CalculateMemPoolAncestors(entry, setAncestors, Limits::NoLimits(), dummy);
10551040
return addUnchecked(entry, setAncestors, validFeeEstimate);
10561041
}
10571042

0 commit comments

Comments
 (0)