Bitcoin Core 28.0.0
P2P Digital Currency
Loading...
Searching...
No Matches
txmempool.cpp
Go to the documentation of this file.
1// Copyright (c) 2009-2010 Satoshi Nakamoto
2// Copyright (c) 2009-2022 The Bitcoin Core developers
3// Distributed under the MIT software license, see the accompanying
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6#include <txmempool.h>
7
8#include <chain.h>
9#include <coins.h>
10#include <common/system.h>
11#include <consensus/consensus.h>
12#include <consensus/tx_verify.h>
14#include <logging.h>
15#include <policy/policy.h>
16#include <policy/settings.h>
17#include <random.h>
18#include <tinyformat.h>
19#include <util/check.h>
20#include <util/feefrac.h>
21#include <util/moneystr.h>
22#include <util/overflow.h>
23#include <util/result.h>
24#include <util/time.h>
25#include <util/trace.h>
26#include <util/translation.h>
27#include <validationinterface.h>
28
29#include <algorithm>
30#include <cmath>
31#include <numeric>
32#include <optional>
33#include <ranges>
34#include <string_view>
35#include <utility>
36
37bool TestLockPointValidity(CChain& active_chain, const LockPoints& lp)
38{
40 // If there are relative lock times then the maxInputBlock will be set
41 // If there are no relative lock times, the LockPoints don't depend on the chain
42 if (lp.maxInputBlock) {
43 // Check whether active_chain is an extension of the block at which the LockPoints
44 // calculation was valid. If not LockPoints are no longer valid
45 if (!active_chain.Contains(lp.maxInputBlock)) {
46 return false;
47 }
48 }
49
50 // LockPoints still valid
51 return true;
52}
53
54void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap& cachedDescendants,
55 const std::set<uint256>& setExclude, std::set<uint256>& descendants_to_remove)
56{
57 CTxMemPoolEntry::Children stageEntries, descendants;
58 stageEntries = updateIt->GetMemPoolChildrenConst();
59
60 while (!stageEntries.empty()) {
61 const CTxMemPoolEntry& descendant = *stageEntries.begin();
62 descendants.insert(descendant);
63 stageEntries.erase(descendant);
64 const CTxMemPoolEntry::Children& children = descendant.GetMemPoolChildrenConst();
65 for (const CTxMemPoolEntry& childEntry : children) {
66 cacheMap::iterator cacheIt = cachedDescendants.find(mapTx.iterator_to(childEntry));
67 if (cacheIt != cachedDescendants.end()) {
68 // We've already calculated this one, just add the entries for this set
69 // but don't traverse again.
70 for (txiter cacheEntry : cacheIt->second) {
71 descendants.insert(*cacheEntry);
72 }
73 } else if (!descendants.count(childEntry)) {
74 // Schedule for later processing
75 stageEntries.insert(childEntry);
76 }
77 }
78 }
79 // descendants now contains all in-mempool descendants of updateIt.
80 // Update and add to cached descendant map
81 int32_t modifySize = 0;
82 CAmount modifyFee = 0;
83 int64_t modifyCount = 0;
84 for (const CTxMemPoolEntry& descendant : descendants) {
85 if (!setExclude.count(descendant.GetTx().GetHash())) {
86 modifySize += descendant.GetTxSize();
87 modifyFee += descendant.GetModifiedFee();
88 modifyCount++;
89 cachedDescendants[updateIt].insert(mapTx.iterator_to(descendant));
90 // Update ancestor state for each descendant
91 mapTx.modify(mapTx.iterator_to(descendant), [=](CTxMemPoolEntry& e) {
92 e.UpdateAncestorState(updateIt->GetTxSize(), updateIt->GetModifiedFee(), 1, updateIt->GetSigOpCost());
93 });
94 // Don't directly remove the transaction here -- doing so would
95 // invalidate iterators in cachedDescendants. Mark it for removal
96 // by inserting into descendants_to_remove.
97 if (descendant.GetCountWithAncestors() > uint64_t(m_opts.limits.ancestor_count) || descendant.GetSizeWithAncestors() > m_opts.limits.ancestor_size_vbytes) {
98 descendants_to_remove.insert(descendant.GetTx().GetHash());
99 }
100 }
101 }
102 mapTx.modify(updateIt, [=](CTxMemPoolEntry& e) { e.UpdateDescendantState(modifySize, modifyFee, modifyCount); });
103}
104
105void CTxMemPool::UpdateTransactionsFromBlock(const std::vector<uint256>& vHashesToUpdate)
106{
108 // For each entry in vHashesToUpdate, store the set of in-mempool, but not
109 // in-vHashesToUpdate transactions, so that we don't have to recalculate
110 // descendants when we come across a previously seen entry.
111 cacheMap mapMemPoolDescendantsToUpdate;
112
113 // Use a set for lookups into vHashesToUpdate (these entries are already
114 // accounted for in the state of their ancestors)
115 std::set<uint256> setAlreadyIncluded(vHashesToUpdate.begin(), vHashesToUpdate.end());
116
117 std::set<uint256> descendants_to_remove;
118
119 // Iterate in reverse, so that whenever we are looking at a transaction
120 // we are sure that all in-mempool descendants have already been processed.
121 // This maximizes the benefit of the descendant cache and guarantees that
122 // CTxMemPoolEntry::m_children will be updated, an assumption made in
123 // UpdateForDescendants.
124 for (const uint256& hash : vHashesToUpdate | std::views::reverse) {
125 // calculate children from mapNextTx
126 txiter it = mapTx.find(hash);
127 if (it == mapTx.end()) {
128 continue;
129 }
130 auto iter = mapNextTx.lower_bound(COutPoint(Txid::FromUint256(hash), 0));
131 // First calculate the children, and update CTxMemPoolEntry::m_children to
132 // include them, and update their CTxMemPoolEntry::m_parents to include this tx.
133 // we cache the in-mempool children to avoid duplicate updates
134 {
136 for (; iter != mapNextTx.end() && iter->first->hash == hash; ++iter) {
137 const uint256 &childHash = iter->second->GetHash();
138 txiter childIter = mapTx.find(childHash);
139 assert(childIter != mapTx.end());
140 // We can skip updating entries we've encountered before or that
141 // are in the block (which are already accounted for).
142 if (!visited(childIter) && !setAlreadyIncluded.count(childHash)) {
143 UpdateChild(it, childIter, true);
144 UpdateParent(childIter, it, true);
145 }
146 }
147 } // release epoch guard for UpdateForDescendants
148 UpdateForDescendants(it, mapMemPoolDescendantsToUpdate, setAlreadyIncluded, descendants_to_remove);
149 }
150
151 for (const auto& txid : descendants_to_remove) {
152 // This txid may have been removed already in a prior call to removeRecursive.
153 // Therefore we ensure it is not yet removed already.
154 if (const std::optional<txiter> txiter = GetIter(txid)) {
156 }
157 }
158}
159
161 int64_t entry_size,
162 size_t entry_count,
163 CTxMemPoolEntry::Parents& staged_ancestors,
164 const Limits& limits) const
165{
166 int64_t totalSizeWithAncestors = entry_size;
167 setEntries ancestors;
168
169 while (!staged_ancestors.empty()) {
170 const CTxMemPoolEntry& stage = staged_ancestors.begin()->get();
171 txiter stageit = mapTx.iterator_to(stage);
172
173 ancestors.insert(stageit);
174 staged_ancestors.erase(stage);
175 totalSizeWithAncestors += stageit->GetTxSize();
176
177 if (stageit->GetSizeWithDescendants() + entry_size > limits.descendant_size_vbytes) {
178 return util::Error{Untranslated(strprintf("exceeds descendant size limit for tx %s [limit: %u]", stageit->GetTx().GetHash().ToString(), limits.descendant_size_vbytes))};
179 } else if (stageit->GetCountWithDescendants() + entry_count > static_cast<uint64_t>(limits.descendant_count)) {
180 return util::Error{Untranslated(strprintf("too many descendants for tx %s [limit: %u]", stageit->GetTx().GetHash().ToString(), limits.descendant_count))};
181 } else if (totalSizeWithAncestors > limits.ancestor_size_vbytes) {
182 return util::Error{Untranslated(strprintf("exceeds ancestor size limit [limit: %u]", limits.ancestor_size_vbytes))};
183 }
184
185 const CTxMemPoolEntry::Parents& parents = stageit->GetMemPoolParentsConst();
186 for (const CTxMemPoolEntry& parent : parents) {
187 txiter parent_it = mapTx.iterator_to(parent);
188
189 // If this is a new ancestor, add it.
190 if (ancestors.count(parent_it) == 0) {
191 staged_ancestors.insert(parent);
192 }
193 if (staged_ancestors.size() + ancestors.size() + entry_count > static_cast<uint64_t>(limits.ancestor_count)) {
194 return util::Error{Untranslated(strprintf("too many unconfirmed ancestors [limit: %u]", limits.ancestor_count))};
195 }
196 }
197 }
198
199 return ancestors;
200}
201
203 const int64_t total_vsize) const
204{
205 size_t pack_count = package.size();
206
207 // Package itself is busting mempool limits; should be rejected even if no staged_ancestors exist
208 if (pack_count > static_cast<uint64_t>(m_opts.limits.ancestor_count)) {
209 return util::Error{Untranslated(strprintf("package count %u exceeds ancestor count limit [limit: %u]", pack_count, m_opts.limits.ancestor_count))};
210 } else if (pack_count > static_cast<uint64_t>(m_opts.limits.descendant_count)) {
211 return util::Error{Untranslated(strprintf("package count %u exceeds descendant count limit [limit: %u]", pack_count, m_opts.limits.descendant_count))};
212 } else if (total_vsize > m_opts.limits.ancestor_size_vbytes) {
213 return util::Error{Untranslated(strprintf("package size %u exceeds ancestor size limit [limit: %u]", total_vsize, m_opts.limits.ancestor_size_vbytes))};
214 } else if (total_vsize > m_opts.limits.descendant_size_vbytes) {
215 return util::Error{Untranslated(strprintf("package size %u exceeds descendant size limit [limit: %u]", total_vsize, m_opts.limits.descendant_size_vbytes))};
216 }
217
218 CTxMemPoolEntry::Parents staged_ancestors;
219 for (const auto& tx : package) {
220 for (const auto& input : tx->vin) {
221 std::optional<txiter> piter = GetIter(input.prevout.hash);
222 if (piter) {
223 staged_ancestors.insert(**piter);
224 if (staged_ancestors.size() + package.size() > static_cast<uint64_t>(m_opts.limits.ancestor_count)) {
225 return util::Error{Untranslated(strprintf("too many unconfirmed parents [limit: %u]", m_opts.limits.ancestor_count))};
226 }
227 }
228 }
229 }
230 // When multiple transactions are passed in, the ancestors and descendants of all transactions
231 // considered together must be within limits even if they are not interdependent. This may be
232 // stricter than the limits for each individual transaction.
233 const auto ancestors{CalculateAncestorsAndCheckLimits(total_vsize, package.size(),
234 staged_ancestors, m_opts.limits)};
235 // It's possible to overestimate the ancestor/descendant totals.
236 if (!ancestors.has_value()) return util::Error{Untranslated("possibly " + util::ErrorString(ancestors).original)};
237 return {};
238}
239
241 const CTxMemPoolEntry &entry,
242 const Limits& limits,
243 bool fSearchForParents /* = true */) const
244{
245 CTxMemPoolEntry::Parents staged_ancestors;
246 const CTransaction &tx = entry.GetTx();
247
248 if (fSearchForParents) {
249 // Get parents of this transaction that are in the mempool
250 // GetMemPoolParents() is only valid for entries in the mempool, so we
251 // iterate mapTx to find parents.
252 for (unsigned int i = 0; i < tx.vin.size(); i++) {
253 std::optional<txiter> piter = GetIter(tx.vin[i].prevout.hash);
254 if (piter) {
255 staged_ancestors.insert(**piter);
256 if (staged_ancestors.size() + 1 > static_cast<uint64_t>(limits.ancestor_count)) {
257 return util::Error{Untranslated(strprintf("too many unconfirmed parents [limit: %u]", limits.ancestor_count))};
258 }
259 }
260 }
261 } else {
262 // If we're not searching for parents, we require this to already be an
263 // entry in the mempool and use the entry's cached parents.
264 txiter it = mapTx.iterator_to(entry);
265 staged_ancestors = it->GetMemPoolParentsConst();
266 }
267
268 return CalculateAncestorsAndCheckLimits(entry.GetTxSize(), /*entry_count=*/1, staged_ancestors,
269 limits);
270}
271
273 std::string_view calling_fn_name,
274 const CTxMemPoolEntry &entry,
275 const Limits& limits,
276 bool fSearchForParents /* = true */) const
277{
278 auto result{CalculateMemPoolAncestors(entry, limits, fSearchForParents)};
279 if (!Assume(result)) {
280 LogPrintLevel(BCLog::MEMPOOL, BCLog::Level::Error, "%s: CalculateMemPoolAncestors failed unexpectedly, continuing with empty ancestor set (%s)\n",
281 calling_fn_name, util::ErrorString(result).original);
282 }
283 return std::move(result).value_or(CTxMemPool::setEntries{});
284}
285
286void CTxMemPool::UpdateAncestorsOf(bool add, txiter it, setEntries &setAncestors)
287{
288 const CTxMemPoolEntry::Parents& parents = it->GetMemPoolParentsConst();
289 // add or remove this tx as a child of each parent
290 for (const CTxMemPoolEntry& parent : parents) {
291 UpdateChild(mapTx.iterator_to(parent), it, add);
292 }
293 const int32_t updateCount = (add ? 1 : -1);
294 const int32_t updateSize{updateCount * it->GetTxSize()};
295 const CAmount updateFee = updateCount * it->GetModifiedFee();
296 for (txiter ancestorIt : setAncestors) {
297 mapTx.modify(ancestorIt, [=](CTxMemPoolEntry& e) { e.UpdateDescendantState(updateSize, updateFee, updateCount); });
298 }
299}
300
302{
303 int64_t updateCount = setAncestors.size();
304 int64_t updateSize = 0;
305 CAmount updateFee = 0;
306 int64_t updateSigOpsCost = 0;
307 for (txiter ancestorIt : setAncestors) {
308 updateSize += ancestorIt->GetTxSize();
309 updateFee += ancestorIt->GetModifiedFee();
310 updateSigOpsCost += ancestorIt->GetSigOpCost();
311 }
312 mapTx.modify(it, [=](CTxMemPoolEntry& e){ e.UpdateAncestorState(updateSize, updateFee, updateCount, updateSigOpsCost); });
313}
314
316{
317 const CTxMemPoolEntry::Children& children = it->GetMemPoolChildrenConst();
318 for (const CTxMemPoolEntry& updateIt : children) {
319 UpdateParent(mapTx.iterator_to(updateIt), it, false);
320 }
321}
322
323void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove, bool updateDescendants)
324{
325 // For each entry, walk back all ancestors and decrement size associated with this
326 // transaction
327 if (updateDescendants) {
328 // updateDescendants should be true whenever we're not recursively
329 // removing a tx and all its descendants, eg when a transaction is
330 // confirmed in a block.
331 // Here we only update statistics and not data in CTxMemPool::Parents
332 // and CTxMemPoolEntry::Children (which we need to preserve until we're
333 // finished with all operations that need to traverse the mempool).
334 for (txiter removeIt : entriesToRemove) {
335 setEntries setDescendants;
336 CalculateDescendants(removeIt, setDescendants);
337 setDescendants.erase(removeIt); // don't update state for self
338 int32_t modifySize = -removeIt->GetTxSize();
339 CAmount modifyFee = -removeIt->GetModifiedFee();
340 int modifySigOps = -removeIt->GetSigOpCost();
341 for (txiter dit : setDescendants) {
342 mapTx.modify(dit, [=](CTxMemPoolEntry& e){ e.UpdateAncestorState(modifySize, modifyFee, -1, modifySigOps); });
343 }
344 }
345 }
346 for (txiter removeIt : entriesToRemove) {
347 const CTxMemPoolEntry &entry = *removeIt;
348 // Since this is a tx that is already in the mempool, we can call CMPA
349 // with fSearchForParents = false. If the mempool is in a consistent
350 // state, then using true or false should both be correct, though false
351 // should be a bit faster.
352 // However, if we happen to be in the middle of processing a reorg, then
353 // the mempool can be in an inconsistent state. In this case, the set
354 // of ancestors reachable via GetMemPoolParents()/GetMemPoolChildren()
355 // will be the same as the set of ancestors whose packages include this
356 // transaction, because when we add a new transaction to the mempool in
357 // addUnchecked(), we assume it has no children, and in the case of a
358 // reorg where that assumption is false, the in-mempool children aren't
359 // linked to the in-block tx's until UpdateTransactionsFromBlock() is
360 // called.
361 // So if we're being called during a reorg, ie before
362 // UpdateTransactionsFromBlock() has been called, then
363 // GetMemPoolParents()/GetMemPoolChildren() will differ from the set of
364 // mempool parents we'd calculate by searching, and it's important that
365 // we use the cached notion of ancestor transactions as the set of
366 // things to update for removal.
367 auto ancestors{AssumeCalculateMemPoolAncestors(__func__, entry, Limits::NoLimits(), /*fSearchForParents=*/false)};
368 // Note that UpdateAncestorsOf severs the child links that point to
369 // removeIt in the entries for the parents of removeIt.
370 UpdateAncestorsOf(false, removeIt, ancestors);
371 }
372 // After updating all the ancestor sizes, we can now sever the link between each
373 // transaction being removed and any mempool children (ie, update CTxMemPoolEntry::m_parents
374 // for each direct child of a transaction being removed).
375 for (txiter removeIt : entriesToRemove) {
376 UpdateChildrenForRemoval(removeIt);
377 }
378}
379
380void CTxMemPoolEntry::UpdateDescendantState(int32_t modifySize, CAmount modifyFee, int64_t modifyCount)
381{
382 nSizeWithDescendants += modifySize;
385 m_count_with_descendants += modifyCount;
387}
388
389void CTxMemPoolEntry::UpdateAncestorState(int32_t modifySize, CAmount modifyFee, int64_t modifyCount, int64_t modifySigOps)
390{
391 nSizeWithAncestors += modifySize;
394 m_count_with_ancestors += modifyCount;
396 nSigOpCostWithAncestors += modifySigOps;
398}
399
402{
403 opts.check_ratio = std::clamp<int>(opts.check_ratio, 0, 1'000'000);
404 int64_t descendant_limit_bytes = opts.limits.descendant_size_vbytes * 40;
405 if (opts.max_size_bytes < 0 || opts.max_size_bytes < descendant_limit_bytes) {
406 error = strprintf(_("-maxmempool must be at least %d MB"), std::ceil(descendant_limit_bytes / 1'000'000.0));
407 }
408 return std::move(opts);
409}
410
412 : m_opts{Flatten(std::move(opts), error)}
413{
414}
415
416bool CTxMemPool::isSpent(const COutPoint& outpoint) const
417{
418 LOCK(cs);
419 return mapNextTx.count(outpoint);
420}
421
423{
425}
426
428{
430}
431
432void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, setEntries &setAncestors)
433{
434 // Add to memory pool without checking anything.
435 // Used by AcceptToMemoryPool(), which DOES do
436 // all the appropriate checks.
437 indexed_transaction_set::iterator newit = mapTx.emplace(CTxMemPoolEntry::ExplicitCopy, entry).first;
438
439 // Update transaction for any feeDelta created by PrioritiseTransaction
440 CAmount delta{0};
441 ApplyDelta(entry.GetTx().GetHash(), delta);
442 // The following call to UpdateModifiedFee assumes no previous fee modifications
443 Assume(entry.GetFee() == entry.GetModifiedFee());
444 if (delta) {
445 mapTx.modify(newit, [&delta](CTxMemPoolEntry& e) { e.UpdateModifiedFee(delta); });
446 }
447
448 // Update cachedInnerUsage to include contained transaction's usage.
449 // (When we update the entry for in-mempool parents, memory usage will be
450 // further updated.)
451 cachedInnerUsage += entry.DynamicMemoryUsage();
452
453 const CTransaction& tx = newit->GetTx();
454 std::set<Txid> setParentTransactions;
455 for (unsigned int i = 0; i < tx.vin.size(); i++) {
456 mapNextTx.insert(std::make_pair(&tx.vin[i].prevout, &tx));
457 setParentTransactions.insert(tx.vin[i].prevout.hash);
458 }
459 // Don't bother worrying about child transactions of this one.
460 // Normal case of a new transaction arriving is that there can't be any
461 // children, because such children would be orphans.
462 // An exception to that is if a transaction enters that used to be in a block.
463 // In that case, our disconnect block logic will call UpdateTransactionsFromBlock
464 // to clean up the mess we're leaving here.
465
466 // Update ancestors with information about this tx
467 for (const auto& pit : GetIterSet(setParentTransactions)) {
468 UpdateParent(newit, pit, true);
469 }
470 UpdateAncestorsOf(true, newit, setAncestors);
471 UpdateEntryForAncestors(newit, setAncestors);
472
474 totalTxSize += entry.GetTxSize();
475 m_total_fee += entry.GetFee();
476
477 txns_randomized.emplace_back(newit->GetSharedTx());
478 newit->idx_randomized = txns_randomized.size() - 1;
479
480 TRACE3(mempool, added,
481 entry.GetTx().GetHash().data(),
482 entry.GetTxSize(),
483 entry.GetFee()
484 );
485}
486
488{
489 // We increment mempool sequence value no matter removal reason
490 // even if not directly reported below.
491 uint64_t mempool_sequence = GetAndIncrementSequence();
492
493 if (reason != MemPoolRemovalReason::BLOCK && m_opts.signals) {
494 // Notify clients that a transaction has been removed from the mempool
495 // for any reason except being included in a block. Clients interested
496 // in transactions included in blocks can subscribe to the BlockConnected
497 // notification.
498 m_opts.signals->TransactionRemovedFromMempool(it->GetSharedTx(), reason, mempool_sequence);
499 }
500 TRACE5(mempool, removed,
501 it->GetTx().GetHash().data(),
502 RemovalReasonToString(reason).c_str(),
503 it->GetTxSize(),
504 it->GetFee(),
505 std::chrono::duration_cast<std::chrono::duration<std::uint64_t>>(it->GetTime()).count()
506 );
507
508 for (const CTxIn& txin : it->GetTx().vin)
509 mapNextTx.erase(txin.prevout);
510
511 RemoveUnbroadcastTx(it->GetTx().GetHash(), true /* add logging because unchecked */);
512
513 if (txns_randomized.size() > 1) {
514 // Update idx_randomized of the to-be-moved entry.
515 Assert(GetEntry(txns_randomized.back()->GetHash()))->idx_randomized = it->idx_randomized;
516 // Remove entry from txns_randomized by replacing it with the back and deleting the back.
517 txns_randomized[it->idx_randomized] = std::move(txns_randomized.back());
518 txns_randomized.pop_back();
519 if (txns_randomized.size() * 2 < txns_randomized.capacity())
520 txns_randomized.shrink_to_fit();
521 } else
522 txns_randomized.clear();
523
524 totalTxSize -= it->GetTxSize();
525 m_total_fee -= it->GetFee();
526 cachedInnerUsage -= it->DynamicMemoryUsage();
527 cachedInnerUsage -= memusage::DynamicUsage(it->GetMemPoolParentsConst()) + memusage::DynamicUsage(it->GetMemPoolChildrenConst());
528 mapTx.erase(it);
530}
531
532// Calculates descendants of entry that are not already in setDescendants, and adds to
533// setDescendants. Assumes entryit is already a tx in the mempool and CTxMemPoolEntry::m_children
534// is correct for tx and all descendants.
535// Also assumes that if an entry is in setDescendants already, then all
536// in-mempool descendants of it are already in setDescendants as well, so that we
537// can save time by not iterating over those entries.
538void CTxMemPool::CalculateDescendants(txiter entryit, setEntries& setDescendants) const
539{
540 setEntries stage;
541 if (setDescendants.count(entryit) == 0) {
542 stage.insert(entryit);
543 }
544 // Traverse down the children of entry, only adding children that are not
545 // accounted for in setDescendants already (because those children have either
546 // already been walked, or will be walked in this iteration).
547 while (!stage.empty()) {
548 txiter it = *stage.begin();
549 setDescendants.insert(it);
550 stage.erase(it);
551
552 const CTxMemPoolEntry::Children& children = it->GetMemPoolChildrenConst();
553 for (const CTxMemPoolEntry& child : children) {
554 txiter childiter = mapTx.iterator_to(child);
555 if (!setDescendants.count(childiter)) {
556 stage.insert(childiter);
557 }
558 }
559 }
560}
561
563{
564 // Remove transaction from memory pool
566 setEntries txToRemove;
567 txiter origit = mapTx.find(origTx.GetHash());
568 if (origit != mapTx.end()) {
569 txToRemove.insert(origit);
570 } else {
571 // When recursively removing but origTx isn't in the mempool
572 // be sure to remove any children that are in the pool. This can
573 // happen during chain re-orgs if origTx isn't re-accepted into
574 // the mempool for any reason.
575 for (unsigned int i = 0; i < origTx.vout.size(); i++) {
576 auto it = mapNextTx.find(COutPoint(origTx.GetHash(), i));
577 if (it == mapNextTx.end())
578 continue;
579 txiter nextit = mapTx.find(it->second->GetHash());
580 assert(nextit != mapTx.end());
581 txToRemove.insert(nextit);
582 }
583 }
584 setEntries setAllRemoves;
585 for (txiter it : txToRemove) {
586 CalculateDescendants(it, setAllRemoves);
587 }
588
589 RemoveStaged(setAllRemoves, false, reason);
590}
591
592void CTxMemPool::removeForReorg(CChain& chain, std::function<bool(txiter)> check_final_and_mature)
593{
594 // Remove transactions spending a coinbase which are now immature and no-longer-final transactions
597
598 setEntries txToRemove;
599 for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
600 if (check_final_and_mature(it)) txToRemove.insert(it);
601 }
602 setEntries setAllRemoves;
603 for (txiter it : txToRemove) {
604 CalculateDescendants(it, setAllRemoves);
605 }
606 RemoveStaged(setAllRemoves, false, MemPoolRemovalReason::REORG);
607 for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
608 assert(TestLockPointValidity(chain, it->GetLockPoints()));
609 }
610}
611
613{
614 // Remove transactions which depend on inputs of tx, recursively
616 for (const CTxIn &txin : tx.vin) {
617 auto it = mapNextTx.find(txin.prevout);
618 if (it != mapNextTx.end()) {
619 const CTransaction &txConflict = *it->second;
620 if (txConflict != tx)
621 {
622 ClearPrioritisation(txConflict.GetHash());
624 }
625 }
626 }
627}
628
632void CTxMemPool::removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight)
633{
635 std::vector<RemovedMempoolTransactionInfo> txs_removed_for_block;
636 txs_removed_for_block.reserve(vtx.size());
637 for (const auto& tx : vtx)
638 {
639 txiter it = mapTx.find(tx->GetHash());
640 if (it != mapTx.end()) {
641 setEntries stage;
642 stage.insert(it);
643 txs_removed_for_block.emplace_back(*it);
645 }
646 removeConflicts(*tx);
648 }
649 if (m_opts.signals) {
650 m_opts.signals->MempoolTransactionsRemovedForBlock(txs_removed_for_block, nBlockHeight);
651 }
652 lastRollingFeeUpdate = GetTime();
653 blockSinceLastRollingFeeBump = true;
654}
655
656void CTxMemPool::check(const CCoinsViewCache& active_coins_tip, int64_t spendheight) const
657{
658 if (m_opts.check_ratio == 0) return;
659
660 if (FastRandomContext().randrange(m_opts.check_ratio) >= 1) return;
661
663 LOCK(cs);
664 LogPrint(BCLog::MEMPOOL, "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size());
665
666 uint64_t checkTotal = 0;
667 CAmount check_total_fee{0};
668 uint64_t innerUsage = 0;
669 uint64_t prev_ancestor_count{0};
670
671 CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(&active_coins_tip));
672
673 for (const auto& it : GetSortedDepthAndScore()) {
674 checkTotal += it->GetTxSize();
675 check_total_fee += it->GetFee();
676 innerUsage += it->DynamicMemoryUsage();
677 const CTransaction& tx = it->GetTx();
678 innerUsage += memusage::DynamicUsage(it->GetMemPoolParentsConst()) + memusage::DynamicUsage(it->GetMemPoolChildrenConst());
679 CTxMemPoolEntry::Parents setParentCheck;
680 for (const CTxIn &txin : tx.vin) {
681 // Check that every mempool transaction's inputs refer to available coins, or other mempool tx's.
682 indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash);
683 if (it2 != mapTx.end()) {
684 const CTransaction& tx2 = it2->GetTx();
685 assert(tx2.vout.size() > txin.prevout.n && !tx2.vout[txin.prevout.n].IsNull());
686 setParentCheck.insert(*it2);
687 }
688 // We are iterating through the mempool entries sorted in order by ancestor count.
689 // All parents must have been checked before their children and their coins added to
690 // the mempoolDuplicate coins cache.
691 assert(mempoolDuplicate.HaveCoin(txin.prevout));
692 // Check whether its inputs are marked in mapNextTx.
693 auto it3 = mapNextTx.find(txin.prevout);
694 assert(it3 != mapNextTx.end());
695 assert(it3->first == &txin.prevout);
696 assert(it3->second == &tx);
697 }
698 auto comp = [](const CTxMemPoolEntry& a, const CTxMemPoolEntry& b) -> bool {
699 return a.GetTx().GetHash() == b.GetTx().GetHash();
700 };
701 assert(setParentCheck.size() == it->GetMemPoolParentsConst().size());
702 assert(std::equal(setParentCheck.begin(), setParentCheck.end(), it->GetMemPoolParentsConst().begin(), comp));
703 // Verify ancestor state is correct.
704 auto ancestors{AssumeCalculateMemPoolAncestors(__func__, *it, Limits::NoLimits())};
705 uint64_t nCountCheck = ancestors.size() + 1;
706 int32_t nSizeCheck = it->GetTxSize();
707 CAmount nFeesCheck = it->GetModifiedFee();
708 int64_t nSigOpCheck = it->GetSigOpCost();
709
710 for (txiter ancestorIt : ancestors) {
711 nSizeCheck += ancestorIt->GetTxSize();
712 nFeesCheck += ancestorIt->GetModifiedFee();
713 nSigOpCheck += ancestorIt->GetSigOpCost();
714 }
715
716 assert(it->GetCountWithAncestors() == nCountCheck);
717 assert(it->GetSizeWithAncestors() == nSizeCheck);
718 assert(it->GetSigOpCostWithAncestors() == nSigOpCheck);
719 assert(it->GetModFeesWithAncestors() == nFeesCheck);
720 // Sanity check: we are walking in ascending ancestor count order.
721 assert(prev_ancestor_count <= it->GetCountWithAncestors());
722 prev_ancestor_count = it->GetCountWithAncestors();
723
724 // Check children against mapNextTx
725 CTxMemPoolEntry::Children setChildrenCheck;
726 auto iter = mapNextTx.lower_bound(COutPoint(it->GetTx().GetHash(), 0));
727 int32_t child_sizes{0};
728 for (; iter != mapNextTx.end() && iter->first->hash == it->GetTx().GetHash(); ++iter) {
729 txiter childit = mapTx.find(iter->second->GetHash());
730 assert(childit != mapTx.end()); // mapNextTx points to in-mempool transactions
731 if (setChildrenCheck.insert(*childit).second) {
732 child_sizes += childit->GetTxSize();
733 }
734 }
735 assert(setChildrenCheck.size() == it->GetMemPoolChildrenConst().size());
736 assert(std::equal(setChildrenCheck.begin(), setChildrenCheck.end(), it->GetMemPoolChildrenConst().begin(), comp));
737 // Also check to make sure size is greater than sum with immediate children.
738 // just a sanity check, not definitive that this calc is correct...
739 assert(it->GetSizeWithDescendants() >= child_sizes + it->GetTxSize());
740
741 TxValidationState dummy_state; // Not used. CheckTxInputs() should always pass
742 CAmount txfee = 0;
743 assert(!tx.IsCoinBase());
744 assert(Consensus::CheckTxInputs(tx, dummy_state, mempoolDuplicate, spendheight, txfee));
745 for (const auto& input: tx.vin) mempoolDuplicate.SpendCoin(input.prevout);
746 AddCoins(mempoolDuplicate, tx, std::numeric_limits<int>::max());
747 }
748 for (auto it = mapNextTx.cbegin(); it != mapNextTx.cend(); it++) {
749 uint256 hash = it->second->GetHash();
750 indexed_transaction_set::const_iterator it2 = mapTx.find(hash);
751 const CTransaction& tx = it2->GetTx();
752 assert(it2 != mapTx.end());
753 assert(&tx == it->second);
754 }
755
756 assert(totalTxSize == checkTotal);
757 assert(m_total_fee == check_total_fee);
758 assert(innerUsage == cachedInnerUsage);
759}
760
761bool CTxMemPool::CompareDepthAndScore(const uint256& hasha, const uint256& hashb, bool wtxid)
762{
763 /* Return `true` if hasha should be considered sooner than hashb. Namely when:
764 * a is not in the mempool, but b is
765 * both are in the mempool and a has fewer ancestors than b
766 * both are in the mempool and a has a higher score than b
767 */
768 LOCK(cs);
769 indexed_transaction_set::const_iterator j = wtxid ? get_iter_from_wtxid(hashb) : mapTx.find(hashb);
770 if (j == mapTx.end()) return false;
771 indexed_transaction_set::const_iterator i = wtxid ? get_iter_from_wtxid(hasha) : mapTx.find(hasha);
772 if (i == mapTx.end()) return true;
773 uint64_t counta = i->GetCountWithAncestors();
774 uint64_t countb = j->GetCountWithAncestors();
775 if (counta == countb) {
776 return CompareTxMemPoolEntryByScore()(*i, *j);
777 }
778 return counta < countb;
779}
780
781namespace {
782class DepthAndScoreComparator
783{
784public:
785 bool operator()(const CTxMemPool::indexed_transaction_set::const_iterator& a, const CTxMemPool::indexed_transaction_set::const_iterator& b)
786 {
787 uint64_t counta = a->GetCountWithAncestors();
788 uint64_t countb = b->GetCountWithAncestors();
789 if (counta == countb) {
790 return CompareTxMemPoolEntryByScore()(*a, *b);
791 }
792 return counta < countb;
793 }
794};
795} // namespace
796
797std::vector<CTxMemPool::indexed_transaction_set::const_iterator> CTxMemPool::GetSortedDepthAndScore() const
798{
799 std::vector<indexed_transaction_set::const_iterator> iters;
801
802 iters.reserve(mapTx.size());
803
804 for (indexed_transaction_set::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi) {
805 iters.push_back(mi);
806 }
807 std::sort(iters.begin(), iters.end(), DepthAndScoreComparator());
808 return iters;
809}
810
811static TxMempoolInfo GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it) {
812 return TxMempoolInfo{it->GetSharedTx(), it->GetTime(), it->GetFee(), it->GetTxSize(), it->GetModifiedFee() - it->GetFee()};
813}
814
815std::vector<CTxMemPoolEntryRef> CTxMemPool::entryAll() const
816{
818
819 std::vector<CTxMemPoolEntryRef> ret;
820 ret.reserve(mapTx.size());
821 for (const auto& it : GetSortedDepthAndScore()) {
822 ret.emplace_back(*it);
823 }
824 return ret;
825}
826
827std::vector<TxMempoolInfo> CTxMemPool::infoAll() const
828{
829 LOCK(cs);
830 auto iters = GetSortedDepthAndScore();
831
832 std::vector<TxMempoolInfo> ret;
833 ret.reserve(mapTx.size());
834 for (auto it : iters) {
835 ret.push_back(GetInfo(it));
836 }
837
838 return ret;
839}
840
842{
844 const auto i = mapTx.find(txid);
845 return i == mapTx.end() ? nullptr : &(*i);
846}
847
849{
850 LOCK(cs);
851 indexed_transaction_set::const_iterator i = mapTx.find(hash);
852 if (i == mapTx.end())
853 return nullptr;
854 return i->GetSharedTx();
855}
856
858{
859 LOCK(cs);
860 indexed_transaction_set::const_iterator i = (gtxid.IsWtxid() ? get_iter_from_wtxid(gtxid.GetHash()) : mapTx.find(gtxid.GetHash()));
861 if (i == mapTx.end())
862 return TxMempoolInfo();
863 return GetInfo(i);
864}
865
866TxMempoolInfo CTxMemPool::info_for_relay(const GenTxid& gtxid, uint64_t last_sequence) const
867{
868 LOCK(cs);
869 indexed_transaction_set::const_iterator i = (gtxid.IsWtxid() ? get_iter_from_wtxid(gtxid.GetHash()) : mapTx.find(gtxid.GetHash()));
870 if (i != mapTx.end() && i->GetSequence() < last_sequence) {
871 return GetInfo(i);
872 } else {
873 return TxMempoolInfo();
874 }
875}
876
877void CTxMemPool::PrioritiseTransaction(const uint256& hash, const CAmount& nFeeDelta)
878{
879 {
880 LOCK(cs);
881 CAmount &delta = mapDeltas[hash];
882 delta = SaturatingAdd(delta, nFeeDelta);
883 txiter it = mapTx.find(hash);
884 if (it != mapTx.end()) {
885 mapTx.modify(it, [&nFeeDelta](CTxMemPoolEntry& e) { e.UpdateModifiedFee(nFeeDelta); });
886 // Now update all ancestors' modified fees with descendants
887 auto ancestors{AssumeCalculateMemPoolAncestors(__func__, *it, Limits::NoLimits(), /*fSearchForParents=*/false)};
888 for (txiter ancestorIt : ancestors) {
889 mapTx.modify(ancestorIt, [=](CTxMemPoolEntry& e){ e.UpdateDescendantState(0, nFeeDelta, 0);});
890 }
891 // Now update all descendants' modified fees with ancestors
892 setEntries setDescendants;
893 CalculateDescendants(it, setDescendants);
894 setDescendants.erase(it);
895 for (txiter descendantIt : setDescendants) {
896 mapTx.modify(descendantIt, [=](CTxMemPoolEntry& e){ e.UpdateAncestorState(0, nFeeDelta, 0, 0); });
897 }
899 }
900 if (delta == 0) {
901 mapDeltas.erase(hash);
902 LogPrintf("PrioritiseTransaction: %s (%sin mempool) delta cleared\n", hash.ToString(), it == mapTx.end() ? "not " : "");
903 } else {
904 LogPrintf("PrioritiseTransaction: %s (%sin mempool) fee += %s, new delta=%s\n",
905 hash.ToString(),
906 it == mapTx.end() ? "not " : "",
907 FormatMoney(nFeeDelta),
908 FormatMoney(delta));
909 }
910 }
911}
912
913void CTxMemPool::ApplyDelta(const uint256& hash, CAmount &nFeeDelta) const
914{
916 std::map<uint256, CAmount>::const_iterator pos = mapDeltas.find(hash);
917 if (pos == mapDeltas.end())
918 return;
919 const CAmount &delta = pos->second;
920 nFeeDelta += delta;
921}
922
924{
926 mapDeltas.erase(hash);
927}
928
929std::vector<CTxMemPool::delta_info> CTxMemPool::GetPrioritisedTransactions() const
930{
932 LOCK(cs);
933 std::vector<delta_info> result;
934 result.reserve(mapDeltas.size());
935 for (const auto& [txid, delta] : mapDeltas) {
936 const auto iter{mapTx.find(txid)};
937 const bool in_mempool{iter != mapTx.end()};
938 std::optional<CAmount> modified_fee;
939 if (in_mempool) modified_fee = iter->GetModifiedFee();
940 result.emplace_back(delta_info{in_mempool, delta, modified_fee, txid});
941 }
942 return result;
943}
944
946{
947 const auto it = mapNextTx.find(prevout);
948 return it == mapNextTx.end() ? nullptr : it->second;
949}
950
951std::optional<CTxMemPool::txiter> CTxMemPool::GetIter(const uint256& txid) const
952{
953 auto it = mapTx.find(txid);
954 if (it != mapTx.end()) return it;
955 return std::nullopt;
956}
957
958CTxMemPool::setEntries CTxMemPool::GetIterSet(const std::set<Txid>& hashes) const
959{
961 for (const auto& h : hashes) {
962 const auto mi = GetIter(h);
963 if (mi) ret.insert(*mi);
964 }
965 return ret;
966}
967
968std::vector<CTxMemPool::txiter> CTxMemPool::GetIterVec(const std::vector<uint256>& txids) const
969{
971 std::vector<txiter> ret;
972 ret.reserve(txids.size());
973 for (const auto& txid : txids) {
974 const auto it{GetIter(txid)};
975 if (!it) return {};
976 ret.push_back(*it);
977 }
978 return ret;
979}
980
982{
983 for (unsigned int i = 0; i < tx.vin.size(); i++)
984 if (exists(GenTxid::Txid(tx.vin[i].prevout.hash)))
985 return false;
986 return true;
987}
988
989CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView* baseIn, const CTxMemPool& mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { }
990
991bool CCoinsViewMemPool::GetCoin(const COutPoint &outpoint, Coin &coin) const {
992 // Check to see if the inputs are made available by another tx in the package.
993 // These Coins would not be available in the underlying CoinsView.
994 if (auto it = m_temp_added.find(outpoint); it != m_temp_added.end()) {
995 coin = it->second;
996 return true;
997 }
998
999 // If an entry in the mempool exists, always return that one, as it's guaranteed to never
1000 // conflict with the underlying cache, and it cannot have pruned entries (as it contains full)
1001 // transactions. First checking the underlying cache risks returning a pruned entry instead.
1002 CTransactionRef ptx = mempool.get(outpoint.hash);
1003 if (ptx) {
1004 if (outpoint.n < ptx->vout.size()) {
1005 coin = Coin(ptx->vout[outpoint.n], MEMPOOL_HEIGHT, false);
1006 m_non_base_coins.emplace(outpoint);
1007 return true;
1008 } else {
1009 return false;
1010 }
1011 }
1012 return base->GetCoin(outpoint, coin);
1013}
1014
1016{
1017 for (unsigned int n = 0; n < tx->vout.size(); ++n) {
1018 m_temp_added.emplace(COutPoint(tx->GetHash(), n), Coin(tx->vout[n], MEMPOOL_HEIGHT, false));
1019 m_non_base_coins.emplace(tx->GetHash(), n);
1020 }
1021}
1023{
1024 m_temp_added.clear();
1025 m_non_base_coins.clear();
1026}
1027
1029 LOCK(cs);
1030 // Estimate the overhead of mapTx to be 15 pointers + an allocation, as no exact formula for boost::multi_index_contained is implemented.
1031 return memusage::MallocUsage(sizeof(CTxMemPoolEntry) + 15 * sizeof(void*)) * mapTx.size() + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + memusage::DynamicUsage(txns_randomized) + cachedInnerUsage;
1032}
1033
1034void CTxMemPool::RemoveUnbroadcastTx(const uint256& txid, const bool unchecked) {
1035 LOCK(cs);
1036
1037 if (m_unbroadcast_txids.erase(txid))
1038 {
1039 LogPrint(BCLog::MEMPOOL, "Removed %i from set of unbroadcast txns%s\n", txid.GetHex(), (unchecked ? " before confirmation that txn was sent out" : ""));
1040 }
1041}
1042
1043void CTxMemPool::RemoveStaged(setEntries &stage, bool updateDescendants, MemPoolRemovalReason reason) {
1045 UpdateForRemoveFromMempool(stage, updateDescendants);
1046 for (txiter it : stage) {
1047 removeUnchecked(it, reason);
1048 }
1049}
1050
1051int CTxMemPool::Expire(std::chrono::seconds time)
1052{
1054 indexed_transaction_set::index<entry_time>::type::iterator it = mapTx.get<entry_time>().begin();
1055 setEntries toremove;
1056 while (it != mapTx.get<entry_time>().end() && it->GetTime() < time) {
1057 toremove.insert(mapTx.project<0>(it));
1058 it++;
1059 }
1060 setEntries stage;
1061 for (txiter removeit : toremove) {
1062 CalculateDescendants(removeit, stage);
1063 }
1065 return stage.size();
1066}
1067
1069{
1070 auto ancestors{AssumeCalculateMemPoolAncestors(__func__, entry, Limits::NoLimits())};
1071 return addUnchecked(entry, ancestors);
1072}
1073
1074void CTxMemPool::UpdateChild(txiter entry, txiter child, bool add)
1075{
1078 if (add && entry->GetMemPoolChildren().insert(*child).second) {
1079 cachedInnerUsage += memusage::IncrementalDynamicUsage(s);
1080 } else if (!add && entry->GetMemPoolChildren().erase(*child)) {
1081 cachedInnerUsage -= memusage::IncrementalDynamicUsage(s);
1082 }
1083}
1084
1085void CTxMemPool::UpdateParent(txiter entry, txiter parent, bool add)
1086{
1089 if (add && entry->GetMemPoolParents().insert(*parent).second) {
1090 cachedInnerUsage += memusage::IncrementalDynamicUsage(s);
1091 } else if (!add && entry->GetMemPoolParents().erase(*parent)) {
1092 cachedInnerUsage -= memusage::IncrementalDynamicUsage(s);
1093 }
1094}
1095
1096CFeeRate CTxMemPool::GetMinFee(size_t sizelimit) const {
1097 LOCK(cs);
1098 if (!blockSinceLastRollingFeeBump || rollingMinimumFeeRate == 0)
1099 return CFeeRate(llround(rollingMinimumFeeRate));
1100
1101 int64_t time = GetTime();
1102 if (time > lastRollingFeeUpdate + 10) {
1103 double halflife = ROLLING_FEE_HALFLIFE;
1104 if (DynamicMemoryUsage() < sizelimit / 4)
1105 halflife /= 4;
1106 else if (DynamicMemoryUsage() < sizelimit / 2)
1107 halflife /= 2;
1108
1109 rollingMinimumFeeRate = rollingMinimumFeeRate / pow(2.0, (time - lastRollingFeeUpdate) / halflife);
1110 lastRollingFeeUpdate = time;
1111
1112 if (rollingMinimumFeeRate < (double)m_opts.incremental_relay_feerate.GetFeePerK() / 2) {
1113 rollingMinimumFeeRate = 0;
1114 return CFeeRate(0);
1115 }
1116 }
1117 return std::max(CFeeRate(llround(rollingMinimumFeeRate)), m_opts.incremental_relay_feerate);
1118}
1119
1122 if (rate.GetFeePerK() > rollingMinimumFeeRate) {
1123 rollingMinimumFeeRate = rate.GetFeePerK();
1124 blockSinceLastRollingFeeBump = false;
1125 }
1126}
1127
1128void CTxMemPool::TrimToSize(size_t sizelimit, std::vector<COutPoint>* pvNoSpendsRemaining) {
1130
1131 unsigned nTxnRemoved = 0;
1132 CFeeRate maxFeeRateRemoved(0);
1133 while (!mapTx.empty() && DynamicMemoryUsage() > sizelimit) {
1134 indexed_transaction_set::index<descendant_score>::type::iterator it = mapTx.get<descendant_score>().begin();
1135
1136 // We set the new mempool min fee to the feerate of the removed set, plus the
1137 // "minimum reasonable fee rate" (ie some value under which we consider txn
1138 // to have 0 fee). This way, we don't allow txn to enter mempool with feerate
1139 // equal to txn which were removed with no block in between.
1140 CFeeRate removed(it->GetModFeesWithDescendants(), it->GetSizeWithDescendants());
1142 trackPackageRemoved(removed);
1143 maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed);
1144
1145 setEntries stage;
1146 CalculateDescendants(mapTx.project<0>(it), stage);
1147 nTxnRemoved += stage.size();
1148
1149 std::vector<CTransaction> txn;
1150 if (pvNoSpendsRemaining) {
1151 txn.reserve(stage.size());
1152 for (txiter iter : stage)
1153 txn.push_back(iter->GetTx());
1154 }
1156 if (pvNoSpendsRemaining) {
1157 for (const CTransaction& tx : txn) {
1158 for (const CTxIn& txin : tx.vin) {
1159 if (exists(GenTxid::Txid(txin.prevout.hash))) continue;
1160 pvNoSpendsRemaining->push_back(txin.prevout);
1161 }
1162 }
1163 }
1164 }
1165
1166 if (maxFeeRateRemoved > CFeeRate(0)) {
1167 LogPrint(BCLog::MEMPOOL, "Removed %u txn, rolling minimum fee bumped to %s\n", nTxnRemoved, maxFeeRateRemoved.ToString());
1168 }
1169}
1170
1172 // find parent with highest descendant count
1173 std::vector<txiter> candidates;
1174 setEntries counted;
1175 candidates.push_back(entry);
1176 uint64_t maximum = 0;
1177 while (candidates.size()) {
1178 txiter candidate = candidates.back();
1179 candidates.pop_back();
1180 if (!counted.insert(candidate).second) continue;
1181 const CTxMemPoolEntry::Parents& parents = candidate->GetMemPoolParentsConst();
1182 if (parents.size() == 0) {
1183 maximum = std::max(maximum, candidate->GetCountWithDescendants());
1184 } else {
1185 for (const CTxMemPoolEntry& i : parents) {
1186 candidates.push_back(mapTx.iterator_to(i));
1187 }
1188 }
1189 }
1190 return maximum;
1191}
1192
1193void CTxMemPool::GetTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants, size_t* const ancestorsize, CAmount* const ancestorfees) const {
1194 LOCK(cs);
1195 auto it = mapTx.find(txid);
1196 ancestors = descendants = 0;
1197 if (it != mapTx.end()) {
1198 ancestors = it->GetCountWithAncestors();
1199 if (ancestorsize) *ancestorsize = it->GetSizeWithAncestors();
1200 if (ancestorfees) *ancestorfees = it->GetModFeesWithAncestors();
1201 descendants = CalculateDescendantMaximum(it);
1202 }
1203}
1204
1206{
1207 LOCK(cs);
1208 return m_load_tried;
1209}
1210
1211void CTxMemPool::SetLoadTried(bool load_tried)
1212{
1213 LOCK(cs);
1214 m_load_tried = load_tried;
1215}
1216
1217std::vector<CTxMemPool::txiter> CTxMemPool::GatherClusters(const std::vector<uint256>& txids) const
1218{
1220 std::vector<txiter> clustered_txs{GetIterVec(txids)};
1221 // Use epoch: visiting an entry means we have added it to the clustered_txs vector. It does not
1222 // necessarily mean the entry has been processed.
1224 for (const auto& it : clustered_txs) {
1225 visited(it);
1226 }
1227 // i = index of where the list of entries to process starts
1228 for (size_t i{0}; i < clustered_txs.size(); ++i) {
1229 // DoS protection: if there are 500 or more entries to process, just quit.
1230 if (clustered_txs.size() > 500) return {};
1231 const txiter& tx_iter = clustered_txs.at(i);
1232 for (const auto& entries : {tx_iter->GetMemPoolParentsConst(), tx_iter->GetMemPoolChildrenConst()}) {
1233 for (const CTxMemPoolEntry& entry : entries) {
1234 const auto entry_it = mapTx.iterator_to(entry);
1235 if (!visited(entry_it)) {
1236 clustered_txs.push_back(entry_it);
1237 }
1238 }
1239 }
1240 }
1241 return clustered_txs;
1242}
1243
1244std::optional<std::string> CTxMemPool::CheckConflictTopology(const setEntries& direct_conflicts)
1245{
1246 for (const auto& direct_conflict : direct_conflicts) {
1247 // Ancestor and descendant counts are inclusive of the tx itself.
1248 const auto ancestor_count{direct_conflict->GetCountWithAncestors()};
1249 const auto descendant_count{direct_conflict->GetCountWithDescendants()};
1250 const bool has_ancestor{ancestor_count > 1};
1251 const bool has_descendant{descendant_count > 1};
1252 const auto& txid_string{direct_conflict->GetSharedTx()->GetHash().ToString()};
1253 // The only allowed configurations are:
1254 // 1 ancestor and 0 descendant
1255 // 0 ancestor and 1 descendant
1256 // 0 ancestor and 0 descendant
1257 if (ancestor_count > 2) {
1258 return strprintf("%s has %u ancestors, max 1 allowed", txid_string, ancestor_count - 1);
1259 } else if (descendant_count > 2) {
1260 return strprintf("%s has %u descendants, max 1 allowed", txid_string, descendant_count - 1);
1261 } else if (has_ancestor && has_descendant) {
1262 return strprintf("%s has both ancestor and descendant, exceeding cluster limit of 2", txid_string);
1263 }
1264 // Additionally enforce that:
1265 // If we have a child, we are its only parent.
1266 // If we have a parent, we are its only child.
1267 if (has_descendant) {
1268 const auto& our_child = direct_conflict->GetMemPoolChildrenConst().begin();
1269 if (our_child->get().GetCountWithAncestors() > 2) {
1270 return strprintf("%s is not the only parent of child %s",
1271 txid_string, our_child->get().GetSharedTx()->GetHash().ToString());
1272 }
1273 } else if (has_ancestor) {
1274 const auto& our_parent = direct_conflict->GetMemPoolParentsConst().begin();
1275 if (our_parent->get().GetCountWithDescendants() > 2) {
1276 return strprintf("%s is not the only child of parent %s",
1277 txid_string, our_parent->get().GetSharedTx()->GetHash().ToString());
1278 }
1279 }
1280 }
1281 return std::nullopt;
1282}
1283
1284util::Result<std::pair<std::vector<FeeFrac>, std::vector<FeeFrac>>> CTxMemPool::CalculateChunksForRBF(CAmount replacement_fees, int64_t replacement_vsize, const setEntries& direct_conflicts, const setEntries& all_conflicts)
1285{
1286 Assume(replacement_vsize > 0);
1287
1288 auto err_string{CheckConflictTopology(direct_conflicts)};
1289 if (err_string.has_value()) {
1290 // Unsupported topology for calculating a feerate diagram
1291 return util::Error{Untranslated(err_string.value())};
1292 }
1293
1294 // new diagram will have chunks that consist of each ancestor of
1295 // direct_conflicts that is at its own fee/size, along with the replacement
1296 // tx/package at its own fee/size
1297
1298 // old diagram will consist of the ancestors and descendants of each element of
1299 // all_conflicts. every such transaction will either be at its own feerate (followed
1300 // by any descendant at its own feerate), or as a single chunk at the descendant's
1301 // ancestor feerate.
1302
1303 std::vector<FeeFrac> old_chunks;
1304 // Step 1: build the old diagram.
1305
1306 // The above clusters are all trivially linearized;
1307 // they have a strict topology of 1 or two connected transactions.
1308
1309 // OLD: Compute existing chunks from all affected clusters
1310 for (auto txiter : all_conflicts) {
1311 // Does this transaction have descendants?
1312 if (txiter->GetCountWithDescendants() > 1) {
1313 // Consider this tx when we consider the descendant.
1314 continue;
1315 }
1316 // Does this transaction have ancestors?
1317 FeeFrac individual{txiter->GetModifiedFee(), txiter->GetTxSize()};
1318 if (txiter->GetCountWithAncestors() > 1) {
1319 // We'll add chunks for either the ancestor by itself and this tx
1320 // by itself, or for a combined package.
1321 FeeFrac package{txiter->GetModFeesWithAncestors(), static_cast<int32_t>(txiter->GetSizeWithAncestors())};
1322 if (individual >> package) {
1323 // The individual feerate is higher than the package, and
1324 // therefore higher than the parent's fee. Chunk these
1325 // together.
1326 old_chunks.emplace_back(package);
1327 } else {
1328 // Add two points, one for the parent and one for this child.
1329 old_chunks.emplace_back(package - individual);
1330 old_chunks.emplace_back(individual);
1331 }
1332 } else {
1333 old_chunks.emplace_back(individual);
1334 }
1335 }
1336
1337 // No topology restrictions post-chunking; sort
1338 std::sort(old_chunks.begin(), old_chunks.end(), std::greater());
1339
1340 std::vector<FeeFrac> new_chunks;
1341
1342 /* Step 2: build the NEW diagram
1343 * CON = Conflicts of proposed chunk
1344 * CNK = Proposed chunk
1345 * NEW = OLD - CON + CNK: New diagram includes all chunks in OLD, minus
1346 * the conflicts, plus the proposed chunk
1347 */
1348
1349 // OLD - CON: Add any parents of direct conflicts that are not conflicted themselves
1350 for (auto direct_conflict : direct_conflicts) {
1351 // If a direct conflict has an ancestor that is not in all_conflicts,
1352 // it can be affected by the replacement of the child.
1353 if (direct_conflict->GetMemPoolParentsConst().size() > 0) {
1354 // Grab the parent.
1355 const CTxMemPoolEntry& parent = direct_conflict->GetMemPoolParentsConst().begin()->get();
1356 if (!all_conflicts.count(mapTx.iterator_to(parent))) {
1357 // This transaction would be left over, so add to the NEW
1358 // diagram.
1359 new_chunks.emplace_back(parent.GetModifiedFee(), parent.GetTxSize());
1360 }
1361 }
1362 }
1363 // + CNK: Add the proposed chunk itself
1364 new_chunks.emplace_back(replacement_fees, int32_t(replacement_vsize));
1365
1366 // No topology restrictions post-chunking; sort
1367 std::sort(new_chunks.begin(), new_chunks.end(), std::greater());
1368 return std::make_pair(old_chunks, new_chunks);
1369}
int64_t CAmount
Amount in satoshis (Can be negative)
Definition amount.h:12
int ret
#define Assert(val)
Identity function.
Definition check.h:77
#define Assume(val)
Assume is the identity function.
Definition check.h:89
An in-memory indexed chain of blocks.
Definition chain.h:417
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
Definition chain.h:447
CCoinsView backed by another CCoinsView.
Definition coins.h:341
CCoinsView * base
Definition coins.h:343
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Definition coins.h:360
Abstract view on the open txout dataset.
Definition coins.h:304
virtual bool GetCoin(const COutPoint &outpoint, Coin &coin) const
Retrieve the Coin (unspent transaction output) for a given outpoint.
Definition coins.cpp:12
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override
GetCoin, returning whether it exists and is not spent.
void Reset()
Clear m_temp_added and m_non_base_coins.
std::unordered_map< COutPoint, Coin, SaltedOutpointHasher > m_temp_added
Coins made available by transactions being validated.
Definition txmempool.h:840
CCoinsViewMemPool(CCoinsView *baseIn, const CTxMemPool &mempoolIn)
std::unordered_set< COutPoint, SaltedOutpointHasher > m_non_base_coins
Set of all coins that have been fetched from mempool or created using PackageAddTransaction (not base...
Definition txmempool.h:846
void PackageAddTransaction(const CTransactionRef &tx)
Add the coins created by this transaction.
const CTxMemPool & mempool
Definition txmempool.h:848
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
Definition feerate.h:33
std::string ToString(const FeeEstimateMode &fee_estimate_mode=FeeEstimateMode::BTC_KVB) const
Definition feerate.cpp:39
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
Definition feerate.h:63
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition transaction.h:29
uint32_t n
Definition transaction.h:32
The basic transaction that is broadcasted on the network and contained in blocks.
const std::vector< CTxOut > vout
bool IsCoinBase() const
const Txid & GetHash() const LIFETIMEBOUND
const std::vector< CTxIn > vin
An input of a transaction.
Definition transaction.h:67
COutPoint prevout
Definition transaction.h:69
CTxMemPoolEntry stores data about the corresponding transaction, as well as data about all in-mempool...
int64_t nSigOpCostWithAncestors
int64_t m_count_with_descendants
number of descendant transactions
void UpdateAncestorState(int32_t modifySize, CAmount modifyFee, int64_t modifyCount, int64_t modifySigOps)
const CTransaction & GetTx() const
CAmount nModFeesWithAncestors
const Children & GetMemPoolChildrenConst() const
std::set< CTxMemPoolEntryRef, CompareIteratorByHash > Children
const Parents & GetMemPoolParentsConst() const
void UpdateModifiedFee(CAmount fee_diff)
size_t DynamicMemoryUsage() const
CAmount nModFeesWithDescendants
... and total fees (all including us)
int32_t GetTxSize() const
int64_t nSizeWithDescendants
... and size
std::set< CTxMemPoolEntryRef, CompareIteratorByHash > Parents
int64_t m_count_with_ancestors
const CAmount & GetFee() const
void UpdateDescendantState(int32_t modifySize, CAmount modifyFee, int64_t modifyCount)
CAmount GetModifiedFee() const
static constexpr ExplicitCopyTag ExplicitCopy
int64_t nSizeWithAncestors
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition txmempool.h:304
void removeConflicts(const CTransaction &tx) EXCLUSIVE_LOCKS_REQUIRED(cs)
std::atomic< unsigned int > nTransactionsUpdated
Used by getblocktemplate to trigger CreateNewBlock() invocation.
Definition txmempool.h:306
void RemoveUnbroadcastTx(const uint256 &txid, const bool unchecked=false)
Removes a transaction from the unbroadcast set.
void PrioritiseTransaction(const uint256 &hash, const CAmount &nFeeDelta)
Affect CreateNewBlock prioritisation of transactions.
setEntries AssumeCalculateMemPoolAncestors(std::string_view calling_fn_name, const CTxMemPoolEntry &entry, const Limits &limits, bool fSearchForParents=true) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Same as CalculateMemPoolAncestors, but always returns a (non-optional) setEntries.
bool HasNoInputsOf(const CTransaction &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Check that none of this transactions inputs are in the mempool, and thus the tx is not dependent on o...
setEntries GetIterSet(const std::set< Txid > &hashes) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Translate a set of hashes into a set of pool iterators to avoid repeated lookups.
std::vector< txiter > GetIterVec(const std::vector< uint256 > &txids) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Translate a list of hashes into a list of mempool iterators to avoid repeated lookups.
void UpdateEntryForAncestors(txiter it, const setEntries &setAncestors) EXCLUSIVE_LOCKS_REQUIRED(cs)
Set ancestor state for an entry.
bool GetLoadTried() const
bool visited(const txiter it) const EXCLUSIVE_LOCKS_REQUIRED(cs
visited marks a CTxMemPoolEntry as having been traversed during the lifetime of the most recently cre...
CFeeRate GetMinFee() const
The minimum fee to get into the mempool, which may itself not be enough for larger-sized transactions...
Definition txmempool.h:614
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
Definition txmempool.h:390
void ClearPrioritisation(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs)
void trackPackageRemoved(const CFeeRate &rate) EXCLUSIVE_LOCKS_REQUIRED(cs)
util::Result< setEntries > CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, const Limits &limits, bool fSearchForParents=true) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Try to calculate all in-mempool ancestors of entry.
void removeRecursive(const CTransaction &tx, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
void TrimToSize(size_t sizelimit, std::vector< COutPoint > *pvNoSpendsRemaining=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs)
Remove transactions from the mempool until its dynamic size is <= sizelimit.
void UpdateTransactionsFromBlock(const std::vector< uint256 > &vHashesToUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs
UpdateTransactionsFromBlock is called when adding transactions from a disconnected block back to the ...
return !it visited * it
Definition txmempool.h:817
void AddTransactionsUpdated(unsigned int n)
void UpdateChildrenForRemoval(txiter entry) EXCLUSIVE_LOCKS_REQUIRED(cs)
Sever link between specified transaction and direct children.
std::optional< txiter > GetIter(const uint256 &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Returns an iterator to the given hash, if found.
util::Result< setEntries > CalculateAncestorsAndCheckLimits(int64_t entry_size, size_t entry_count, CTxMemPoolEntry::Parents &staged_ancestors, const Limits &limits) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Helper function to calculate all in-mempool ancestors of staged_ancestors and apply ancestor and desc...
CTransactionRef get(const uint256 &hash) const
size_t DynamicMemoryUsage() const
const Options m_opts
Definition txmempool.h:439
void check(const CCoinsViewCache &active_coins_tip, int64_t spendheight) const EXCLUSIVE_LOCKS_REQUIRED(voi addUnchecked)(const CTxMemPoolEntry &entry) EXCLUSIVE_LOCKS_REQUIRED(cs
If sanity-checking is turned on, check makes sure the pool is consistent (does not contain two transa...
Definition txmempool.h:463
std::vector< TxMempoolInfo > infoAll() const
void GetTransactionAncestry(const uint256 &txid, size_t &ancestors, size_t &descendants, size_t *ancestorsize=nullptr, CAmount *ancestorfees=nullptr) const
Calculate the ancestor and descendant count for the given transaction.
void check(const CCoinsViewCache &active_coins_tip, int64_t spendheight) const EXCLUSIVE_LOCKS_REQUIRED(voi cs_main)
Definition txmempool.h:463
CTxMemPool(Options opts, bilingual_str &error)
Create a new CTxMemPool.
void UpdateParent(txiter entry, txiter parent, bool add) EXCLUSIVE_LOCKS_REQUIRED(cs)
void removeUnchecked(txiter entry, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
Before calling removeUnchecked for a given transaction, UpdateForRemoveFromMempool must be called on ...
int Expire(std::chrono::seconds time) EXCLUSIVE_LOCKS_REQUIRED(cs)
Expire all transaction (and their dependencies) in the mempool older than time.
txiter get_iter_from_wtxid(const uint256 &wtxid) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition txmempool.h:677
void UpdateAncestorsOf(bool add, txiter hash, setEntries &setAncestors) EXCLUSIVE_LOCKS_REQUIRED(cs)
Update ancestors of hash to add/remove it as a descendant transaction.
void removeForReorg(CChain &chain, std::function< bool(txiter)> filter_final_and_mature) EXCLUSIVE_LOCKS_REQUIRED(cs
After reorg, filter the entries that would no longer be valid in the next block, and update the entri...
util::Result< void > CheckPackageLimits(const Package &package, int64_t total_vsize) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Calculate all in-mempool ancestors of a set of transactions not already in the mempool and check ance...
TxMempoolInfo info(const GenTxid &gtxid) const
std::vector< txiter > GatherClusters(const std::vector< uint256 > &txids) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Collect the entire cluster of connected transactions for each transaction in txids.
void ApplyDelta(const uint256 &hash, CAmount &nFeeDelta) const EXCLUSIVE_LOCKS_REQUIRED(cs)
void UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendants, const std::set< uint256 > &setExclude, std::set< uint256 > &descendants_to_remove) EXCLUSIVE_LOCKS_REQUIRED(cs)
UpdateForDescendants is used by UpdateTransactionsFromBlock to update the descendants for a single tr...
Definition txmempool.cpp:54
util::Result< std::pair< std::vector< FeeFrac >, std::vector< FeeFrac > > > CalculateChunksForRBF(CAmount replacement_fees, int64_t replacement_vsize, const setEntries &direct_conflicts, const setEntries &all_conflicts) EXCLUSIVE_LOCKS_REQUIRED(cs)
Calculate the sorted chunks for the old and new mempool relating to the clusters that would be affect...
static const int ROLLING_FEE_HALFLIFE
Definition txmempool.h:330
std::vector< indexed_transaction_set::const_iterator > GetSortedDepthAndScore() const EXCLUSIVE_LOCKS_REQUIRED(cs)
void RemoveStaged(setEntries &stage, bool updateDescendants, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
Remove a set of transactions from the mempool.
void removeForBlock(const std::vector< CTransactionRef > &vtx, unsigned int nBlockHeight) EXCLUSIVE_LOCKS_REQUIRED(cs)
Called when a block is connected.
std::vector< delta_info > GetPrioritisedTransactions() const EXCLUSIVE_LOCKS_REQUIRED(!cs)
Return a vector of all entries in mapDeltas with their corresponding delta_info.
indexed_transaction_set::nth_index< 0 >::type::const_iterator txiter
Definition txmempool.h:393
uint64_t GetAndIncrementSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs)
Guards this internal counter for external reporting.
Definition txmempool.h:719
void UpdateChild(txiter entry, txiter child, bool add) EXCLUSIVE_LOCKS_REQUIRED(cs)
TxMempoolInfo info_for_relay(const GenTxid &gtxid, uint64_t last_sequence) const
Returns info for a transaction if its entry_sequence < last_sequence.
bool exists(const GenTxid &gtxid) const
Definition txmempool.h:665
bool m_epoch
Definition txmempool.h:810
std::set< txiter, CompareIteratorByHash > setEntries
Definition txmempool.h:396
const CTransaction * GetConflictTx(const COutPoint &prevout) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Get the transaction in the pool that spends the same prevout.
bool CompareDepthAndScore(const uint256 &hasha, const uint256 &hashb, bool wtxid=false)
void CalculateDescendants(txiter it, setEntries &setDescendants) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Populate setDescendants with all in-mempool descendants of hash.
std::optional< std::string > CheckConflictTopology(const setEntries &direct_conflicts)
void SetLoadTried(bool load_tried)
Set whether or not an initial attempt to load the persisted mempool was made (regardless of whether t...
void UpdateForRemoveFromMempool(const setEntries &entriesToRemove, bool updateDescendants) EXCLUSIVE_LOCKS_REQUIRED(cs)
For each transaction being removed, update ancestors and any direct children.
std::vector< CTxMemPoolEntryRef > entryAll() const EXCLUSIVE_LOCKS_REQUIRED(cs)
uint64_t CalculateDescendantMaximum(txiter entry) const EXCLUSIVE_LOCKS_REQUIRED(cs)
bool isSpent(const COutPoint &outpoint) const
const CTxMemPoolEntry * GetEntry(const Txid &txid) const LIFETIMEBOUND EXCLUSIVE_LOCKS_REQUIRED(cs)
std::map< txiter, setEntries, CompareIteratorByHash > cacheMap
Definition txmempool.h:402
unsigned int GetTransactionsUpdated() const
A UTXO entry.
Definition coins.h:33
Sort by feerate of entry (fee/size) in descending order This is only used for transaction relay,...
Definition txmempool.h:137
Fast randomness source.
Definition random.h:377
A generic txid reference (txid or wtxid).
bool IsWtxid() const
const uint256 & GetHash() const LIFETIMEBOUND
static GenTxid Txid(const uint256 &hash)
void MempoolTransactionsRemovedForBlock(const std::vector< RemovedMempoolTransactionInfo > &, unsigned int nBlockHeight)
void TransactionRemovedFromMempool(const CTransactionRef &, MemPoolRemovalReason, uint64_t mempool_sequence)
std::string GetHex() const
Definition uint256.cpp:11
std::string ToString() const
Definition uint256.cpp:47
constexpr const std::byte * data() const
static transaction_identifier FromUint256(const uint256 &id)
256-bit opaque blob.
Definition uint256.h:178
void AddCoins(CCoinsViewCache &cache, const CTransaction &tx, int nHeight, bool check_for_overwrite)
Utility function to add all of a transaction's outputs to a cache.
Definition coins.cpp:121
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition cs_main.cpp:8
#define WITH_FRESH_EPOCH(epoch)
Definition epochguard.h:100
#define LogPrintLevel(category, level,...)
Definition logging.h:281
#define LogPrint(category,...)
Definition logging.h:293
#define LogPrintf(...)
Definition logging.h:274
LockPoints lp
std::string RemovalReasonToString(const MemPoolRemovalReason &r) noexcept
MemPoolRemovalReason
Reason why a transaction was removed from the mempool, this is passed to the notification signal.
@ SIZELIMIT
Removed in size limiting.
@ BLOCK
Removed for block.
@ EXPIRY
Expired from mempool.
@ CONFLICT
Removed for conflict with in-block transaction.
@ REORG
Removed for reorganization.
std::string FormatMoney(const CAmount n)
Money parsing/formatting utilities.
Definition moneystr.cpp:19
@ MEMPOOL
Definition logging.h:44
bool CheckTxInputs(const CTransaction &tx, TxValidationState &state, const CCoinsViewCache &inputs, int nSpendHeight, CAmount &txfee)
Check whether all inputs of this transaction are valid (no double spends and amounts) This does not m...
static size_t DynamicUsage(const int8_t &v)
Dynamic memory usage for built-in types is zero.
Definition memusage.h:30
static size_t IncrementalDynamicUsage(const std::set< X, Y > &s)
Definition memusage.h:106
static size_t MallocUsage(size_t alloc)
Compute the total memory used by allocating alloc bytes.
Definition memusage.h:51
bilingual_str ErrorString(const Result< T > &result)
Definition result.h:93
T SaturatingAdd(const T i, const T j) noexcept
Definition overflow.h:33
std::vector< CTransactionRef > Package
A package is an ordered list of transactions.
Definition packages.h:50
std::shared_ptr< const CTransaction > CTransactionRef
Data structure storing a fee and size, ordered by increasing fee/size.
Definition feefrac.h:39
CBlockIndex * maxInputBlock
Information about a mempool transaction.
Definition txmempool.h:213
Bilingual messages:
Definition translation.h:18
Options struct containing limit options for a CTxMemPool.
static constexpr MemPoolLimits NoLimits()
int64_t descendant_count
The maximum allowed number of transactions in a package including the entry and its descendants.
int64_t descendant_size_vbytes
The maximum allowed size in virtual bytes of an entry and its descendants within a package.
int64_t ancestor_count
The maximum allowed number of transactions in a package including the entry and its ancestors.
int64_t ancestor_size_vbytes
The maximum allowed size in virtual bytes of an entry and its ancestors within a package.
Options struct containing options for constructing a CTxMemPool.
ValidationSignals * signals
#define AssertLockNotHeld(cs)
Definition sync.h:147
#define LOCK(cs)
Definition sync.h:257
#define AssertLockHeld(cs)
Definition sync.h:142
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
Definition time.cpp:44
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
#define TRACE3(context, event, a, b, c)
Definition trace.h:33
#define TRACE5(context, event, a, b, c, d, e)
Definition trace.h:35
bilingual_str _(ConstevalStringLiteral str)
Translation function.
Definition translation.h:80
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition translation.h:48
static CTxMemPool::Options && Flatten(CTxMemPool::Options &&opts, bilingual_str &error)
Clamp option values and populate the error if options are not valid.
bool TestLockPointValidity(CChain &active_chain, const LockPoints &lp)
Test whether the LockPoints height and time are still valid on the current chain.
Definition txmempool.cpp:37
static TxMempoolInfo GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it)
static const uint32_t MEMPOOL_HEIGHT
Fake height value used in Coin to signify they are only in the memory pool (since 0....
Definition txmempool.h:49
bool TestLockPointValidity(CChain &active_chain, const LockPoints &lp) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Test whether the LockPoints height and time are still valid on the current chain.
Definition txmempool.cpp:37
assert(!tx.IsCoinBase())