Bitcoin ABC 0.33.11
P2P Digital Currency
txmempool.cpp
Go to the documentation of this file.
1// Copyright (c) 2009-2010 Satoshi Nakamoto
2// Copyright (c) 2009-2016 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 <blockindex.h>
9#include <clientversion.h>
10#include <coins.h>
11#include <common/system.h>
12#include <config.h>
13#include <consensus/consensus.h>
14#include <consensus/tx_verify.h>
16#include <logging.h>
17#include <policy/fees.h>
18#include <policy/policy.h>
19#include <reverse_iterator.h>
20#include <undo.h>
21#include <util/check.h>
22#include <util/moneystr.h>
23#include <util/time.h>
24#include <validationinterface.h>
25
26#include <algorithm>
27#include <cmath>
28#include <limits>
29#include <vector>
30
32 setEntries &setAncestors,
33 CTxMemPoolEntry::Parents &staged_ancestors) const {
34 while (!staged_ancestors.empty()) {
35 const auto stage = staged_ancestors.begin()->get();
36
37 txiter stageit = mapTx.find(stage->GetTx().GetId());
38 assert(stageit != mapTx.end());
39 setAncestors.insert(stageit);
40 staged_ancestors.erase(staged_ancestors.begin());
41
42 const CTxMemPoolEntry::Parents &parents =
43 (*stageit)->GetMemPoolParentsConst();
44 for (const auto &parent : parents) {
45 txiter parent_it = mapTx.find(parent.get()->GetTx().GetId());
46 assert(parent_it != mapTx.end());
47
48 // If this is a new ancestor, add it.
49 if (setAncestors.count(parent_it) == 0) {
50 staged_ancestors.insert(parent);
51 }
52 }
53 }
54
55 return true;
56}
57
59 const CTxMemPoolEntryRef &entry, setEntries &setAncestors,
60 bool fSearchForParents /* = true */) const {
61 CTxMemPoolEntry::Parents staged_ancestors;
62 const CTransaction &tx = entry->GetTx();
63
64 if (fSearchForParents) {
65 // Get parents of this transaction that are in the mempool
66 // GetMemPoolParents() is only valid for entries in the mempool, so we
67 // iterate mapTx to find parents.
68 for (const CTxIn &in : tx.vin) {
69 std::optional<txiter> piter = GetIter(in.prevout.GetTxId());
70 if (!piter) {
71 continue;
72 }
73 staged_ancestors.insert(**piter);
74 }
75 } else {
76 // If we're not searching for parents, we require this to be an entry in
77 // the mempool already.
78 staged_ancestors = entry->GetMemPoolParentsConst();
79 }
80
81 return CalculateAncestors(setAncestors, staged_ancestors);
82}
83
85 // add or remove this tx as a child of each parent
86 for (const auto &parent : (*it)->GetMemPoolParentsConst()) {
87 auto parent_it = mapTx.find(parent.get()->GetTx().GetId());
88 assert(parent_it != mapTx.end());
89 UpdateChild(parent_it, it, add);
90 }
91}
92
94 const CTxMemPoolEntry::Children &children =
95 (*it)->GetMemPoolChildrenConst();
96 for (const auto &child : children) {
97 auto updateIt = mapTx.find(child.get()->GetTx().GetId());
98 assert(updateIt != mapTx.end());
99 UpdateParent(updateIt, it, false);
100 }
101}
102
104 for (txiter removeIt : entriesToRemove) {
105 // Note that UpdateParentsOf severs the child links that point to
106 // removeIt in the entries for the parents of removeIt.
107 UpdateParentsOf(false, removeIt);
108 }
109
110 // After updating all the parent links, we can now sever the link between
111 // each transaction being removed and any mempool children (ie, update
112 // CTxMemPoolEntry::m_parents for each direct child of a transaction being
113 // removed).
114 for (txiter removeIt : entriesToRemove) {
115 UpdateChildrenForRemoval(removeIt);
116 }
117}
118
120 : m_finalizedTxsFitter(node::BlockFitter(config)),
121 m_orphanage(std::make_unique<TxOrphanage>()),
122 m_conflicting(std::make_unique<TxConflicting>()),
123 m_opts{std::move(opts)} {
124 // lock free clear
125 _clear();
126}
127
129
130bool CTxMemPool::isSpent(const COutPoint &outpoint) const {
131 LOCK(cs);
132 return mapNextTx.count(outpoint);
133}
134
137}
138
141}
142
144 // get a guaranteed unique id (in case tests re-use the same object)
145 entry->SetEntryId(nextEntryId++);
146
147 // Update transaction for any feeDelta created by PrioritiseTransaction
148 {
149 Amount feeDelta = Amount::zero();
150 ApplyDelta(entry->GetTx().GetId(), feeDelta);
151 // The following call to UpdateModifiedFee assumes no previous fee
152 // modifications
153 Assume(entry->GetFee() == entry->GetModifiedFee());
154 entry->UpdateModifiedFee(feeDelta);
155 }
156
157 // Add to memory pool without checking anything.
158 // Used by AcceptToMemoryPool(), which DOES do all the appropriate checks.
159 auto [newit, inserted] = mapTx.insert(entry);
160 // Sanity check: It is a programming error if insertion fails (uniqueness
161 // invariants in mapTx are violated, etc)
162 assert(inserted);
163 // Sanity check: We should always end up inserting at the end of the
164 // entry_id index
165 assert(&*mapTx.get<entry_id>().rbegin() == &*newit);
166
167 // Update cachedInnerUsage to include contained transaction's usage.
168 // (When we update the entry for in-mempool parents, memory usage will be
169 // further updated.)
170 cachedInnerUsage += entry->DynamicMemoryUsage();
171
172 const CTransactionRef tx = entry->GetSharedTx();
173 std::set<TxId> setParentTransactions;
174 for (const CTxIn &in : tx->vin) {
175 mapNextTx.insert(std::make_pair(&in.prevout, tx));
176 setParentTransactions.insert(in.prevout.GetTxId());
177 }
178 // Don't bother worrying about child transactions of this one. It is
179 // guaranteed that a new transaction arriving will not have any children,
180 // because such children would be orphans.
181
182 // Update ancestors with information about this tx
183 for (const auto &pit : GetIterSet(setParentTransactions)) {
184 UpdateParent(newit, pit, true);
185 }
186
187 UpdateParentsOf(true, newit);
188
190 totalTxSize += entry->GetTxSize();
191 m_total_fee += entry->GetFee();
192}
193
195 // We increment mempool sequence value no matter removal reason
196 // even if not directly reported below.
197 uint64_t mempool_sequence = GetAndIncrementSequence();
198
199 const TxId &txid = (*it)->GetTx().GetId();
200
201 if (reason != MemPoolRemovalReason::BLOCK) {
202 if (m_opts.signals) {
203 // Notify clients that a transaction has been removed from the
204 // mempool for any reason except being included in a block. Clients
205 // interested in transactions included in blocks can subscribe to
206 // the BlockConnected notification.
208 (*it)->GetSharedTx(), reason, mempool_sequence);
209 }
210
211 if (auto removed_tx = finalizedTxs.remove(txid)) {
212 m_finalizedTxsFitter.removeTxUnchecked(removed_tx->GetTxSize(),
213 removed_tx->GetSigChecks(),
214 removed_tx->GetFee());
215 }
216 }
217
218 for (const CTxIn &txin : (*it)->GetTx().vin) {
219 mapNextTx.erase(txin.prevout);
220 }
221
222 /* add logging because unchecked */
223 RemoveUnbroadcastTx(txid, true);
224
225 totalTxSize -= (*it)->GetTxSize();
226 m_total_fee -= (*it)->GetFee();
227 cachedInnerUsage -= (*it)->DynamicMemoryUsage();
228 cachedInnerUsage -=
229 memusage::DynamicUsage((*it)->GetMemPoolParentsConst()) +
230 memusage::DynamicUsage((*it)->GetMemPoolChildrenConst());
231 mapTx.erase(it);
233}
234
235// Calculates descendants of entry that are not already in setDescendants, and
236// adds to setDescendants. Assumes entryit is already a tx in the mempool and
237// CTxMemPoolEntry::m_children is correct for tx and all descendants. Also
238// assumes that if an entry is in setDescendants already, then all in-mempool
239// descendants of it are already in setDescendants as well, so that we can save
240// time by not iterating over those entries.
242 setEntries &setDescendants) const {
243 setEntries stage;
244 if (setDescendants.count(entryit) == 0) {
245 stage.insert(entryit);
246 }
247 // Traverse down the children of entry, only adding children that are not
248 // accounted for in setDescendants already (because those children have
249 // either already been walked, or will be walked in this iteration).
250 while (!stage.empty()) {
251 txiter it = *stage.begin();
252 setDescendants.insert(it);
253 stage.erase(stage.begin());
254
255 const CTxMemPoolEntry::Children &children =
256 (*it)->GetMemPoolChildrenConst();
257 for (const auto &child : children) {
258 txiter childiter = mapTx.find(child.get()->GetTx().GetId());
259 assert(childiter != mapTx.end());
260
261 if (!setDescendants.count(childiter)) {
262 stage.insert(childiter);
263 }
264 }
265 }
266}
267
268void CTxMemPool::removeRecursive(const CTransaction &origTx,
269 MemPoolRemovalReason reason) {
270 // Remove transaction from memory pool.
272 setEntries txToRemove;
273 txiter origit = mapTx.find(origTx.GetId());
274 if (origit != mapTx.end()) {
275 txToRemove.insert(origit);
276 } else {
277 // When recursively removing but origTx isn't in the mempool be sure to
278 // remove any children that are in the pool. This can happen during
279 // chain re-orgs if origTx isn't re-accepted into the mempool for any
280 // reason.
281 auto it = mapNextTx.lower_bound(COutPoint(origTx.GetId(), 0));
282 while (it != mapNextTx.end() &&
283 it->first->GetTxId() == origTx.GetId()) {
284 txiter nextit = mapTx.find(it->second->GetId());
285 assert(nextit != mapTx.end());
286 txToRemove.insert(nextit);
287 ++it;
288 }
289 }
290
291 setEntries setAllRemoves;
292 for (txiter it : txToRemove) {
293 CalculateDescendants(it, setAllRemoves);
294 }
295
296 RemoveStaged(setAllRemoves, reason);
297}
298
299void CTxMemPool::removeConflicts(const CTransaction &tx) {
300 // Remove transactions which depend on inputs of tx, recursively
302 for (const CTxIn &txin : tx.vin) {
303 auto it = mapNextTx.find(txin.prevout);
304 if (it != mapNextTx.end()) {
305 const CTransaction &txConflict = *it->second;
306 if (txConflict != tx) {
307 // We reject blocks that contains a tx conflicting with a
308 // finalized tx, so this should never happen
309 Assume(!isAvalancheFinalizedPreConsensus(txConflict.GetId()));
310 ClearPrioritisation(txConflict.GetId());
312 }
313 }
314 }
315}
316
322 lastRollingFeeUpdate = GetTime();
323 blockSinceLastRollingFeeBump = true;
324}
325
327 const std::unordered_set<TxId, SaltedTxIdHasher>
328 &confirmedTxIdsInNonFinalizedBlocks) {
330
331 std::vector<CTxMemPoolEntryRef> finalizedTxsToKeep;
334 if (mapTx.count(entry->GetTx().GetId()) > 0 ||
335 confirmedTxIdsInNonFinalizedBlocks.count(
336 entry->GetTx().GetId()) > 0) {
337 // The transaction is either in the mempool (not confirmed) or
338 // confirmed in a non-finalized block (which might be rejeted by
339 // avalanche), so we keep it in the radix tree.
340 finalizedTxsToKeep.push_back(entry);
341 }
342
343 // All the other transactions are either confirmed in the finalized
344 // block or in one of its ancestors.
345 return true;
346 });
347
348 // Clear the radix tree and add back the transactions that are not confirmed
349 decltype(finalizedTxs) empty;
350 std::swap(finalizedTxs, empty);
351
352 m_finalizedTxsFitter.resetBlock();
353 for (const auto &entry : finalizedTxsToKeep) {
354 // We don't need to proceed to all the checks that happen during
355 // finalization here so we only recompute the size and sigchecks.
356 if (finalizedTxs.insert(entry)) {
357 m_finalizedTxsFitter.addTx(entry->GetTxSize(),
358 entry->GetSigChecks(), entry->GetFee());
359 }
360 }
361
363}
364
366 mapTx.clear();
367 mapNextTx.clear();
368 totalTxSize = 0;
369 m_total_fee = Amount::zero();
370 cachedInnerUsage = 0;
371 lastRollingFeeUpdate = GetTime();
372 blockSinceLastRollingFeeBump = false;
373 rollingMinimumFeeRate = 0;
375}
376
377void CTxMemPool::clear(bool include_finalized_txs) {
378 LOCK(cs);
379 _clear();
380 if (include_finalized_txs) {
382 std::swap(finalizedTxs, empty);
383 m_finalizedTxsFitter.resetBlock();
384 }
385}
386
387void CTxMemPool::check(const CCoinsViewCache &active_coins_tip,
388 int64_t spendheight) const {
389 if (m_opts.check_ratio == 0) {
390 return;
391 }
392
393 if (FastRandomContext().randrange(m_opts.check_ratio) >= 1) {
394 return;
395 }
396
398 LOCK(cs);
400 "Checking mempool with %u transactions and %u inputs\n",
401 (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size());
402
403 uint64_t checkTotal = 0;
404 Amount check_total_fee{Amount::zero()};
405 uint64_t innerUsage = 0;
406
407 CCoinsViewCache mempoolDuplicate(
408 const_cast<CCoinsViewCache *>(&active_coins_tip));
409
410 for (const CTxMemPoolEntryRef &entry : mapTx.get<entry_id>()) {
411 checkTotal += entry->GetTxSize();
412 check_total_fee += entry->GetFee();
413 innerUsage += entry->DynamicMemoryUsage();
414 const CTransaction &tx = entry->GetTx();
415 innerUsage += memusage::DynamicUsage(entry->GetMemPoolParentsConst()) +
416 memusage::DynamicUsage(entry->GetMemPoolChildrenConst());
417
418 CTxMemPoolEntry::Parents setParentCheck;
419 for (const CTxIn &txin : tx.vin) {
420 // Check that every mempool transaction's inputs refer to available
421 // coins, or other mempool tx's.
422 txiter parentIt = mapTx.find(txin.prevout.GetTxId());
423 if (parentIt != mapTx.end()) {
424 const CTransaction &parentTx = (*parentIt)->GetTx();
425 assert(parentTx.vout.size() > txin.prevout.GetN() &&
426 !parentTx.vout[txin.prevout.GetN()].IsNull());
427 setParentCheck.insert(*parentIt);
428 // also check that parents have a topological ordering before
429 // their children
430 assert((*parentIt)->GetEntryId() < entry->GetEntryId());
431 }
432 // We are iterating through the mempool entries sorted
433 // topologically.
434 // All parents must have been checked before their children and
435 // their coins added to the mempoolDuplicate coins cache.
436 assert(mempoolDuplicate.HaveCoin(txin.prevout));
437 // Check whether its inputs are marked in mapNextTx.
438 auto prevoutNextIt = mapNextTx.find(txin.prevout);
439 assert(prevoutNextIt != mapNextTx.end());
440 assert(prevoutNextIt->first == &txin.prevout);
441 assert(prevoutNextIt->second.get() == &tx);
442 }
443 auto comp = [](const auto &a, const auto &b) -> bool {
444 return a.get()->GetTx().GetId() == b.get()->GetTx().GetId();
445 };
446 assert(setParentCheck.size() == entry->GetMemPoolParentsConst().size());
447 assert(std::equal(setParentCheck.begin(), setParentCheck.end(),
448 entry->GetMemPoolParentsConst().begin(), comp));
449
450 // Verify ancestor state is correct.
451 setEntries setAncestors;
452 std::string dummy;
453
454 const bool ok = CalculateMemPoolAncestors(entry, setAncestors);
455 assert(ok);
456
457 // all ancestors should have entryId < this tx's entryId
458 for (const auto &ancestor : setAncestors) {
459 assert((*ancestor)->GetEntryId() < entry->GetEntryId());
460 }
461
462 // Check children against mapNextTx
463 CTxMemPoolEntry::Children setChildrenCheck;
464 auto iter = mapNextTx.lower_bound(COutPoint(entry->GetTx().GetId(), 0));
465 for (; iter != mapNextTx.end() &&
466 iter->first->GetTxId() == entry->GetTx().GetId();
467 ++iter) {
468 txiter childIt = mapTx.find(iter->second->GetId());
469 // mapNextTx points to in-mempool transactions
470 assert(childIt != mapTx.end());
471 setChildrenCheck.insert(*childIt);
472 }
473 assert(setChildrenCheck.size() ==
474 entry->GetMemPoolChildrenConst().size());
475 assert(std::equal(setChildrenCheck.begin(), setChildrenCheck.end(),
476 entry->GetMemPoolChildrenConst().begin(), comp));
477
478 // Not used. CheckTxInputs() should always pass
479 TxValidationState dummy_state;
480 Amount txfee{Amount::zero()};
481 assert(!tx.IsCoinBase());
482 assert(Consensus::CheckTxInputs(tx, dummy_state, mempoolDuplicate,
483 spendheight, txfee));
484 for (const auto &input : tx.vin) {
485 mempoolDuplicate.SpendCoin(input.prevout);
486 }
487 AddCoins(mempoolDuplicate, tx, std::numeric_limits<int>::max());
488 }
489
490 for (auto &[_, nextTx] : mapNextTx) {
491 txiter it = mapTx.find(nextTx->GetId());
492 assert(it != mapTx.end());
493 assert((*it)->GetSharedTx() == nextTx);
494 }
495
496 assert(totalTxSize == checkTotal);
497 assert(m_total_fee == check_total_fee);
498 assert(innerUsage == cachedInnerUsage);
499}
500
502 const TxId &txidb) const {
503 LOCK(cs);
504 auto it1 = mapTx.find(txida);
505 if (it1 == mapTx.end()) {
506 return false;
507 }
508 auto it2 = mapTx.find(txidb);
509 if (it2 == mapTx.end()) {
510 return true;
511 }
512 return (*it1)->GetEntryId() < (*it2)->GetEntryId();
513}
514
515void CTxMemPool::getAllTxIds(std::vector<TxId> &vtxid) const {
516 LOCK(cs);
517
518 vtxid.clear();
519 vtxid.reserve(mapTx.size());
520
521 for (const auto &entry : mapTx.get<entry_id>()) {
522 vtxid.push_back(entry->GetTx().GetId());
523 }
524}
525
526static TxMempoolInfo
527GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it) {
528 return TxMempoolInfo{(*it)->GetSharedTx(), (*it)->GetTime(),
529 (*it)->GetFee(), (*it)->GetTxSize(),
530 (*it)->GetModifiedFee() - (*it)->GetFee()};
531}
532
533std::vector<TxMempoolInfo> CTxMemPool::infoAll() const {
534 LOCK(cs);
535
536 std::vector<TxMempoolInfo> ret;
537 ret.reserve(mapTx.size());
538
539 const auto &index = mapTx.get<entry_id>();
540 for (auto it = index.begin(); it != index.end(); ++it) {
541 ret.push_back(GetInfo(mapTx.project<0>(it)));
542 }
543
544 return ret;
545}
546
547bool CTxMemPool::setAvalancheFinalized(const CTxMemPoolEntryRef &tx,
548 const Consensus::Params &params,
549 const CBlockIndex &active_chain_tip,
550 std::vector<TxId> &finalizedTxIds) {
553
554 auto it = mapTx.find(tx->GetTx().GetId());
555 if (it == mapTx.end()) {
556 // Trying to finalize a tx that is not in the mempool !
557 LogPrintf("Trying to finalize tx %s that is not in the mempool\n",
558 tx->GetTx().GetId().ToString());
559 return false;
560 }
561
562 setEntries setAncestors;
563 setAncestors.insert(it);
564 if (!CalculateMemPoolAncestors(tx, setAncestors,
565 /*fSearchForParents=*/false)) {
566 // Failed to get a list of parents for this tx. If we finalize it we
567 // might be missing a parent and generate an invalid block.
568 LogPrintf("Failed to calculate ancestors for tx %s\n",
569 tx->GetTx().GetId().ToString());
570 return false;
571 }
572
573 // Make sure the tx chain would fit the block before adding them.
574 uint64_t sumOfTxSize{0};
575 uint64_t sumOfTxSigChecks{0};
576 for (auto iter_it = setAncestors.begin(); iter_it != setAncestors.end();) {
577 // iter_it is an iterator of mapTx iterator (aka txiter)
578 CTxMemPoolEntryRef entry = **iter_it;
579
580 TxValidationState state;
581 if (!ContextualCheckTransactionForCurrentBlock(active_chain_tip, params,
582 entry->GetTx(), state)) {
584 "Delay storing finalized tx %s that would cause the block "
585 "to be invalid%s (%s)\n",
586 tx->GetTx().GetId().ToString(),
587 entry->GetSharedTx()->GetId() == tx->GetSharedTx()->GetId()
588 ? ""
589 : strprintf(" for parent %s",
590 entry->GetSharedTx()->GetId().ToString()),
591 state.ToString());
592 return false;
593 }
594
595 if (m_finalizedTxsFitter.isBelowBlockMinFeeRate(
596 entry->GetModifiedFeeRate())) {
598 "Delay storing finalized tx %s due to fee rate below the "
599 "block mininmum%s (see -blockmintxfee)\n",
600 tx->GetTx().GetId().ToString(),
601 entry->GetSharedTx()->GetId() == tx->GetSharedTx()->GetId()
602 ? ""
603 : strprintf(" for parent %s",
604 entry->GetSharedTx()->GetId().ToString()));
605 return false;
606 }
607
608 // It is possible (and normal) that an ancestor is already finalized.
609 // Beware to not account for it in this case.
610 if (isAvalancheFinalizedPreConsensus(entry->GetTx().GetId())) {
611 iter_it = setAncestors.erase(iter_it);
612 continue;
613 }
614
615 sumOfTxSize += entry->GetTxSize();
616 sumOfTxSigChecks += entry->GetSigChecks();
617 ++iter_it;
618 }
619
620 if (!m_finalizedTxsFitter.testTxFits(sumOfTxSize, sumOfTxSigChecks)) {
621 LogPrint(
623 "Delay storing finalized tx %s as it won't fit in the next block\n",
624 tx->GetTx().GetId().ToString());
625 return false;
626 }
627
628 finalizedTxIds.clear();
629
630 // Now let's add the txs !
631 // At this stage the set of ancestors is free if already finalized txs
632 for (txiter ancestor_it : setAncestors) {
633 if (finalizedTxs.insert(*ancestor_it)) {
634 m_finalizedTxsFitter.addTx((*ancestor_it)->GetTxSize(),
635 (*ancestor_it)->GetSigChecks(),
636 (*ancestor_it)->GetFee());
637
638 finalizedTxIds.push_back((*ancestor_it)->GetTx().GetId());
639
640 if (m_opts.signals) {
642 (*ancestor_it)->GetSharedTx());
643 }
644 }
645 }
646
648
649 return true;
650}
651
655
656 const TxId &txid = tx->GetId();
657 if (auto it = GetIter(txid)) {
658 CTxMemPoolEntryRef entry = **it;
659
660 // The tx is in the mempool, check it would fit the next block or if
661 // it's already full of finalized txs.
662 return !m_finalizedTxsFitter.isBelowBlockMinFeeRate(
663 entry->GetModifiedFeeRate()) &&
664 m_finalizedTxsFitter.testTxFits(entry->GetTxSize(),
665 entry->GetSigChecks());
666 }
667
668 // Otherwise check if it's in the conflicting pool. If we reach this point
669 // this means that the transaction has been rejected so no need to check if
670 // it fits the block, however we don't want to discard it either so the vote
671 // continue until the tx is invalidated.
673 return m_conflicting && m_conflicting->HaveTx(txid));
674}
675
677 LOCK(cs);
678 indexed_transaction_set::const_iterator i = mapTx.find(txid);
679 if (i == mapTx.end()) {
680 return nullptr;
681 }
682
683 return (*i)->GetSharedTx();
684}
685
687 LOCK(cs);
688 indexed_transaction_set::const_iterator i = mapTx.find(txid);
689 if (i == mapTx.end()) {
690 return TxMempoolInfo();
691 }
692
693 return GetInfo(i);
694}
695
697 LOCK(cs);
698
699 // minerPolicy uses recent blocks to figure out a reasonable fee. This
700 // may disagree with the rollingMinimumFeerate under certain scenarios
701 // where the mempool increases rapidly, or blocks are being mined which
702 // do not contain propagated transactions.
703 return std::max(m_opts.min_relay_feerate, GetMinFee());
704}
705
707 const Amount nFeeDelta) {
708 {
709 LOCK(cs);
710 Amount &delta = mapDeltas[txid];
711 delta.SaturatingAdd(nFeeDelta);
712 txiter it = mapTx.find(txid);
713 if (it != mapTx.end()) {
714 mapTx.modify(it, [&nFeeDelta](CTxMemPoolEntryRef &e) {
715 e->UpdateModifiedFee(nFeeDelta);
716 });
718 }
719 }
720 LogPrintf("PrioritiseTransaction: %s fee += %s\n", txid.ToString(),
721 FormatMoney(nFeeDelta));
722}
723
724void CTxMemPool::ApplyDelta(const TxId &txid, Amount &nFeeDelta) const {
726 std::map<TxId, Amount>::const_iterator pos = mapDeltas.find(txid);
727 if (pos == mapDeltas.end()) {
728 return;
729 }
730
731 nFeeDelta += pos->second;
732}
733
736 mapDeltas.erase(txid);
737}
738
739CTransactionRef CTxMemPool::GetConflictTx(const COutPoint &prevout) const {
740 const auto it = mapNextTx.find(prevout);
741 return it == mapNextTx.end() ? nullptr : it->second;
742}
743
744std::optional<CTxMemPool::txiter> CTxMemPool::GetIter(const TxId &txid) const {
745 auto it = mapTx.find(txid);
746 if (it != mapTx.end()) {
747 return it;
748 }
749 return std::nullopt;
750}
751
753CTxMemPool::GetIterSet(const std::set<TxId> &txids) const {
755 for (const auto &txid : txids) {
756 const auto mi = GetIter(txid);
757 if (mi) {
758 ret.insert(*mi);
759 }
760 }
761 return ret;
762}
763
764bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const {
765 for (const CTxIn &in : tx.vin) {
766 if (exists(in.prevout.GetTxId())) {
767 return false;
768 }
769 }
770
771 return true;
772}
773
775 const CTxMemPool &mempoolIn)
776 : CCoinsViewBacked(baseIn), mempool(mempoolIn) {}
777
778std::optional<Coin>
779CCoinsViewMemPool::GetCoin(const COutPoint &outpoint) const {
780 // Check to see if the inputs are made available by another tx in the
781 // package. These Coins would not be available in the underlying CoinsView.
782 if (auto it = m_temp_added.find(outpoint); it != m_temp_added.end()) {
783 return it->second;
784 }
785
786 // If an entry in the mempool exists, always return that one, as it's
787 // guaranteed to never conflict with the underlying cache, and it cannot
788 // have pruned entries (as it contains full) transactions. First checking
789 // the underlying cache risks returning a pruned entry instead.
790 CTransactionRef ptx = mempool.get(outpoint.GetTxId());
791 if (ptx) {
792 if (outpoint.GetN() < ptx->vout.size()) {
793 Coin coin(ptx->vout[outpoint.GetN()], MEMPOOL_HEIGHT, false);
794 m_non_base_coins.emplace(outpoint);
795 return coin;
796 }
797 return std::nullopt;
798 }
799 return base->GetCoin(outpoint);
800}
801
803 for (uint32_t n = 0; n < tx->vout.size(); ++n) {
804 m_temp_added.emplace(COutPoint(tx->GetId(), n),
805 Coin(tx->vout[n], MEMPOOL_HEIGHT, false));
806 m_non_base_coins.emplace(COutPoint(tx->GetId(), n));
807 }
808}
810 m_temp_added.clear();
811 m_non_base_coins.clear();
812}
813
815 LOCK(cs);
816 // Estimate the overhead of mapTx to be 12 pointers + an allocation, as no
817 // exact formula for boost::multi_index_contained is implemented.
819 12 * sizeof(void *)) *
820 mapTx.size() +
821 memusage::DynamicUsage(mapNextTx) +
822 memusage::DynamicUsage(mapDeltas) + cachedInnerUsage;
823}
824
825void CTxMemPool::RemoveUnbroadcastTx(const TxId &txid, const bool unchecked) {
826 LOCK(cs);
827
828 if (m_unbroadcast_txids.erase(txid)) {
829 LogPrint(
830 BCLog::MEMPOOL, "Removed %i from set of unbroadcast txns%s\n",
831 txid.GetHex(),
832 (unchecked ? " before confirmation that txn was sent out" : ""));
833 }
834}
835
837 MemPoolRemovalReason reason) {
840
841 // Remove txs in reverse-topological order
842 const setRevTopoEntries stageRevTopo(stage.begin(), stage.end());
843 for (txiter it : stageRevTopo) {
844 removeUnchecked(it, reason);
845 }
846}
847
848int CTxMemPool::Expire(std::chrono::seconds time) {
850 indexed_transaction_set::index<entry_time>::type::iterator it =
851 mapTx.get<entry_time>().begin();
852 setEntries toremove;
853 size_t skippedFinalizedTxs{0};
854 while (it != mapTx.get<entry_time>().end() && (*it)->GetTime() < time) {
855 if (isAvalancheFinalizedPreConsensus((*it)->GetTx().GetId())) {
856 // Don't expire finalized transactions
857 ++skippedFinalizedTxs;
858 } else {
859 toremove.insert(mapTx.project<0>(it));
860 }
861
862 it++;
863 }
864
865 if (skippedFinalizedTxs > 0) {
866 LogPrint(BCLog::MEMPOOL, "Not expiring %u finalized transaction\n",
867 skippedFinalizedTxs);
868 }
869
870 setEntries stage;
871 for (txiter removeit : toremove) {
872 CalculateDescendants(removeit, stage);
873 }
874
876 return stage.size();
877}
878
882 int expired = Expire(GetTime<std::chrono::seconds>() - m_opts.expiry);
883 if (expired != 0) {
885 "Expired %i transactions from the memory pool\n", expired);
886 }
887
888 std::vector<COutPoint> vNoSpendsRemaining;
889 TrimToSize(m_opts.max_size_bytes, &vNoSpendsRemaining);
890 for (const COutPoint &removed : vNoSpendsRemaining) {
891 coins_cache.Uncache(removed);
892 }
893}
894
895void CTxMemPool::UpdateChild(txiter entry, txiter child, bool add) {
898 if (add && (*entry)->GetMemPoolChildren().insert(*child).second) {
899 cachedInnerUsage += memusage::IncrementalDynamicUsage(s);
900 } else if (!add && (*entry)->GetMemPoolChildren().erase(*child)) {
901 cachedInnerUsage -= memusage::IncrementalDynamicUsage(s);
902 }
903}
904
905void CTxMemPool::UpdateParent(txiter entry, txiter parent, bool add) {
908 if (add && (*entry)->GetMemPoolParents().insert(*parent).second) {
909 cachedInnerUsage += memusage::IncrementalDynamicUsage(s);
910 } else if (!add && (*entry)->GetMemPoolParents().erase(*parent)) {
911 cachedInnerUsage -= memusage::IncrementalDynamicUsage(s);
912 }
913}
914
915CFeeRate CTxMemPool::GetMinFee(size_t sizelimit) const {
916 LOCK(cs);
917 if (!blockSinceLastRollingFeeBump || rollingMinimumFeeRate == 0) {
918 return CFeeRate(int64_t(ceill(rollingMinimumFeeRate)) * SATOSHI);
919 }
920
921 int64_t time = GetTime();
922 if (time > lastRollingFeeUpdate + 10) {
923 double halflife = ROLLING_FEE_HALFLIFE;
924 if (DynamicMemoryUsage() < sizelimit / 4) {
925 halflife /= 4;
926 } else if (DynamicMemoryUsage() < sizelimit / 2) {
927 halflife /= 2;
928 }
929
930 rollingMinimumFeeRate =
931 rollingMinimumFeeRate /
932 pow(2.0, (time - lastRollingFeeUpdate) / halflife);
933 lastRollingFeeUpdate = time;
934 }
935 return CFeeRate(int64_t(ceill(rollingMinimumFeeRate)) * SATOSHI);
936}
937
940 if ((rate.GetFeePerK() / SATOSHI) > rollingMinimumFeeRate) {
941 rollingMinimumFeeRate = rate.GetFeePerK() / SATOSHI;
942 blockSinceLastRollingFeeBump = false;
943 }
944}
945
946void CTxMemPool::TrimToSize(size_t sizelimit,
947 std::vector<COutPoint> *pvNoSpendsRemaining) {
949
950 unsigned nTxnRemoved = 0;
951 size_t finalizedTxsSkipped = 0;
952 CFeeRate maxFeeRateRemoved(Amount::zero());
953 while (!mapTx.empty() && DynamicMemoryUsage() > sizelimit) {
954 auto &by_modified_feerate = mapTx.get<modified_feerate>();
955 // Lowest fee first
956 auto rit = by_modified_feerate.rbegin();
957
958 // We don't evict finalized transactions, even if they have lower fee
959 while (isAvalancheFinalizedPreConsensus((*rit)->GetTx().GetId())) {
960 ++finalizedTxsSkipped;
961 ++rit;
962 if (rit == by_modified_feerate.rend()) {
963 // Nothing we can trim
964 break;
965 }
966 }
967
968 // Convert to forward iterator.
969 // If rit == rend(), the forward iterator will be equivalent to begin()
970 // and we can't decrement it, there is nothing to remove. This could
971 // only happen if all the transactions are finalized, which in turns
972 // implies that the mempool cannot contain a block worth of txs.
973 // In this case we still exit the loop so we get the proper log message.
974 if (rit == by_modified_feerate.rend()) {
975 break;
976 }
977 auto it = rit.base();
978 --it;
979
980 // We set the new mempool min fee to the feerate of the removed
981 // transaction, plus the "minimum reasonable fee rate" (ie some value
982 // under which we consider txn to have 0 fee). This way, we don't allow
983 // txn to enter mempool with feerate equal to txn which were removed
984 // with no block in between.
985 CFeeRate removed = (*it)->GetModifiedFeeRate();
987
988 trackPackageRemoved(removed);
989 maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed);
990
991 setEntries stage;
992 CalculateDescendants(mapTx.project<0>(it), stage);
993 nTxnRemoved += stage.size();
994
995 if (pvNoSpendsRemaining) {
996 for (const txiter &iter : stage) {
997 for (const CTxIn &txin : (*iter)->GetTx().vin) {
998 if (!exists(txin.prevout.GetTxId())) {
999 pvNoSpendsRemaining->push_back(txin.prevout);
1000 }
1001 }
1002 }
1003 }
1004
1006 }
1007
1008 if (maxFeeRateRemoved > CFeeRate(Amount::zero())) {
1010 "Removed %u txn, rolling minimum fee bumped to %s\n",
1011 nTxnRemoved, maxFeeRateRemoved.ToString());
1012 }
1013
1014 if (finalizedTxsSkipped > 0) {
1016 "Not evicting %u finalized txn for low fee\n",
1017 finalizedTxsSkipped);
1018 }
1019}
1020
1022 LOCK(cs);
1023 return m_load_tried;
1024}
1025
1026void CTxMemPool::SetLoadTried(bool load_tried) {
1027 LOCK(cs);
1028 m_load_tried = load_tried;
1029}
1030
1031std::string RemovalReasonToString(const MemPoolRemovalReason &r) noexcept {
1032 switch (r) {
1034 return "expiry";
1036 return "sizelimit";
1038 return "reorg";
1040 return "block";
1042 return "conflict";
1044 return "avalanche";
1046 return "manual";
1047 }
1048 assert(false);
1049}
static constexpr Amount SATOSHI
Definition: amount.h:153
#define Assume(val)
Assume is the identity function.
Definition: check.h:100
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: blockindex.h:25
CCoinsView backed by another CCoinsView.
Definition: coins.h:338
CCoinsView * base
Definition: coins.h:340
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Definition: coins.h:358
void Uncache(const COutPoint &outpoint)
Removes the UTXO with the given outpoint from the cache, if it is not modified.
Definition: coins.cpp:338
Abstract view on the open txout dataset.
Definition: coins.h:304
virtual std::optional< Coin > GetCoin(const COutPoint &outpoint) const
Retrieve the Coin (unspent transaction output) for a given outpoint.
Definition: coins.cpp:13
std::optional< Coin > GetCoin(const COutPoint &outpoint) const override
GetCoin, returning whether it exists and is not spent.
Definition: txmempool.cpp:779
void Reset()
Clear m_temp_added and m_non_base_coins.
Definition: txmempool.cpp:809
std::unordered_map< COutPoint, Coin, SaltedOutpointHasher > m_temp_added
Coins made available by transactions being validated.
Definition: txmempool.h:651
CCoinsViewMemPool(CCoinsView *baseIn, const CTxMemPool &mempoolIn)
Definition: txmempool.cpp:774
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:659
void PackageAddTransaction(const CTransactionRef &tx)
Add the coins created by this transaction.
Definition: txmempool.cpp:802
const CTxMemPool & mempool
Definition: txmempool.h:662
Fee rate in satoshis per kilobyte: Amount / kB.
Definition: feerate.h:21
std::string ToString() const
Definition: feerate.cpp:57
Amount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
Definition: feerate.h:54
CTxMemPoolEntry stores data about the corresponding transaction, as well as data about all in-mempool...
Definition: mempool_entry.h:65
std::set< std::reference_wrapper< const CTxMemPoolEntryRef >, CompareIteratorById > Children
Definition: mempool_entry.h:73
std::set< std::reference_wrapper< const CTxMemPoolEntryRef >, CompareIteratorById > Parents
Definition: mempool_entry.h:70
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:222
void removeConflicts(const CTransaction &tx) EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.cpp:299
CFeeRate estimateFee() const
Definition: txmempool.cpp:696
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...
Definition: txmempool.cpp:764
void ClearPrioritisation(const TxId &txid) EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.cpp:734
std::set< txiter, CompareIteratorById > setEntries
Definition: txmempool.h:320
void RemoveUnbroadcastTx(const TxId &txid, const bool unchecked=false)
Removes a transaction from the unbroadcast set.
Definition: txmempool.cpp:825
bool GetLoadTried() const
Definition: txmempool.cpp:1021
bool CalculateAncestors(setEntries &setAncestors, CTxMemPoolEntry::Parents &staged_ancestors) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Helper function to calculate all in-mempool ancestors of staged_ancestors param@[in] staged_ancestors...
Definition: txmempool.cpp:31
void updateFeeForBlock() EXCLUSIVE_LOCKS_REQUIRED(cs)
Called when a block is connected.
Definition: txmempool.cpp:320
CFeeRate GetMinFee() const
The minimum fee to get into the mempool, which may itself not be enough for larger-sized transactions...
Definition: txmempool.h:456
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
Definition: txmempool.h:316
void trackPackageRemoved(const CFeeRate &rate) EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.cpp:938
void removeRecursive(const CTransaction &tx, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.cpp:268
void UpdateForRemoveFromMempool(const setEntries &entriesToRemove) EXCLUSIVE_LOCKS_REQUIRED(cs)
For each transaction being removed, update ancestors and any direct children.
Definition: txmempool.cpp:103
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.
Definition: txmempool.cpp:946
void AddTransactionsUpdated(unsigned int n)
Definition: txmempool.cpp:139
void UpdateChildrenForRemoval(txiter entry) EXCLUSIVE_LOCKS_REQUIRED(cs)
Sever link between specified transaction and direct children.
Definition: txmempool.cpp:93
bool CompareTopologically(const TxId &txida, const TxId &txidb) const
Definition: txmempool.cpp:501
TxMempoolInfo info(const TxId &txid) const
Definition: txmempool.cpp:686
void getAllTxIds(std::vector< TxId > &vtxid) const
Definition: txmempool.cpp:515
std::atomic< uint32_t > nTransactionsUpdated
Used by getblocktemplate to trigger CreateNewBlock() invocation.
Definition: txmempool.h:225
setEntries GetIterSet(const std::set< TxId > &txids) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Translate a set of txids into a set of pool iterators to avoid repeated lookups.
Definition: txmempool.cpp:753
size_t DynamicMemoryUsage() const
Definition: txmempool.cpp:814
bool setAvalancheFinalized(const CTxMemPoolEntryRef &tx, const Consensus::Params &params, const CBlockIndex &active_chain_tip, std::vector< TxId > &finalizedTxIds) EXCLUSIVE_LOCKS_REQUIRED(bool isAvalancheFinalizedPreConsensus(const TxId &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.h:539
const Options m_opts
Definition: txmempool.h:353
std::vector< TxMempoolInfo > infoAll() const
Definition: txmempool.cpp:533
void LimitSize(CCoinsViewCache &coins_cache) EXCLUSIVE_LOCKS_REQUIRED(cs
Reduce the size of the mempool by expiring and then trimming the mempool.
Definition: txmempool.cpp:879
void UpdateParent(txiter entry, txiter parent, bool add) EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.cpp:905
CTransactionRef GetConflictTx(const COutPoint &prevout) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Get the transaction in the pool that spends the same prevout.
Definition: txmempool.cpp:739
void removeUnchecked(txiter entry, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
Before calling removeUnchecked for a given transaction, UpdateForRemoveFromMempool must be called on ...
Definition: txmempool.cpp:194
int Expire(std::chrono::seconds time) EXCLUSIVE_LOCKS_REQUIRED(cs)
Expire all transaction (and their dependencies) in the mempool older than time.
Definition: txmempool.cpp:848
bool isWorthPolling(const CTransactionRef &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs
Definition: txmempool.cpp:652
std::set< txiter, CompareIteratorByRevEntryId > setRevTopoEntries
Definition: txmempool.h:321
bool exists(const TxId &txid) const
Definition: txmempool.h:528
static const int ROLLING_FEE_HALFLIFE
Definition: txmempool.h:265
CTransactionRef get(const TxId &txid) const
Definition: txmempool.cpp:676
void PrioritiseTransaction(const TxId &txid, const Amount nFeeDelta)
Affect CreateNewBlock prioritisation of transactions.
Definition: txmempool.cpp:706
CTxMemPool(const Config &config, Options opts)
Create a new CTxMemPool.
Definition: txmempool.cpp:119
indexed_transaction_set::nth_index< 0 >::type::const_iterator txiter
Definition: txmempool.h:319
uint64_t GetAndIncrementSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs)
Guards this internal counter for external reporting.
Definition: txmempool.h:579
void UpdateChild(txiter entry, txiter child, bool add) EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.cpp:895
void check(const CCoinsViewCache &active_coins_tip, int64_t spendheight) const EXCLUSIVE_LOCKS_REQUIRED(void addUnchecked(CTxMemPoolEntryRef 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:375
RadixTree< CTxMemPoolEntry, MemPoolEntryRadixTreeAdapter > finalizedTxs
Definition: txmempool.h:323
void check(const CCoinsViewCache &active_coins_tip, int64_t spendheight) const EXCLUSIVE_LOCKS_REQUIRED(void cs_main
Definition: txmempool.h:376
bool CalculateMemPoolAncestors(const CTxMemPoolEntryRef &entry, setEntries &setAncestors, bool fSearchForParents=true) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Try to calculate all in-mempool ancestors of entry.
Definition: txmempool.cpp:58
void removeForFinalizedBlock(const std::unordered_set< TxId, SaltedTxIdHasher > &confirmedTxIdsInNonFinalizedBlocks) EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.cpp:326
void clear(bool include_finalized_txs=false)
Definition: txmempool.cpp:377
Mutex cs_conflicting
Definition: txmempool.h:259
void CalculateDescendants(txiter it, setEntries &setDescendants) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Populate setDescendants with all in-mempool descendants of hash.
Definition: txmempool.cpp:241
void RemoveStaged(const setEntries &stage, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
Remove a set of transactions from the mempool.
Definition: txmempool.cpp:836
void UpdateParentsOf(bool add, txiter it) EXCLUSIVE_LOCKS_REQUIRED(cs)
Update parents of it to add/remove it as a child transaction.
Definition: txmempool.cpp:84
void ApplyDelta(const TxId &txid, Amount &nFeeDelta) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.cpp:724
void SetLoadTried(bool load_tried)
Set whether or not an initial attempt to load the persisted mempool was made (regardless of whether t...
Definition: txmempool.cpp:1026
std::optional< txiter > GetIter(const TxId &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Returns an iterator to the given txid, if found.
Definition: txmempool.cpp:744
bool isSpent(const COutPoint &outpoint) const
Definition: txmempool.cpp:130
unsigned int GetTransactionsUpdated() const
Definition: txmempool.cpp:135
void _clear() EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.cpp:365
A UTXO entry.
Definition: coins.h:31
Definition: config.h:19
Fast randomness source.
Definition: random.h:411
Definition: rcu.h:85
T * get()
Get allows to access the undelying pointer.
Definition: rcu.h:170
void TransactionFinalized(const CTransactionRef &tx)
void TransactionRemovedFromMempool(const CTransactionRef &, MemPoolRemovalReason, uint64_t mempool_sequence)
std::string ToString() const
Definition: validation.h:125
std::string ToString() const
Definition: uint256.h:80
std::string GetHex() const
Definition: uint256.cpp:16
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:158
#define LogPrint(category,...)
Definition: logging.h:452
#define LogPrintf(...)
Definition: logging.h:424
std::string FormatMoney(const Amount amt)
Do not use these functions to represent or parse monetary amounts to or from JSON but use AmountFromV...
Definition: moneystr.cpp:13
@ AVALANCHE
Definition: logging.h:91
@ MEMPOOL
Definition: logging.h:71
bool CheckTxInputs(const CTransaction &tx, TxValidationState &state, const CCoinsViewCache &inputs, int nSpendHeight, Amount &txfee)
Check whether all inputs of this transaction are valid (no double spends and amounts).
Definition: tx_verify.cpp:194
static size_t DynamicUsage(const int8_t &v)
Dynamic memory usage for built-in types is zero.
Definition: memusage.h:28
static size_t IncrementalDynamicUsage(const std::set< X, Y > &s)
Definition: memusage.h:124
static size_t MallocUsage(size_t alloc)
Compute the total memory used by allocating alloc bytes.
Definition: memusage.h:74
Definition: messages.h:12
Implement std::hash so RCUPtr can be used as a key for maps or sets.
Definition: rcu.h:259
static constexpr CFeeRate MEMPOOL_FULL_FEE_INCREMENT(1000 *SATOSHI)
Default for -incrementalrelayfee, which sets the minimum feerate increase for mempool limiting or BIP...
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:315
Definition: amount.h:23
void SaturatingAdd(const Amount &other) noexcept
Amount addition with integer saturation.
Definition: amount.cpp:57
static constexpr Amount zero() noexcept
Definition: amount.h:36
Parameters that influence chain consensus.
Definition: params.h:34
RCUPtr< T > remove(const KeyType &key)
Remove an element from the tree.
Definition: radix.h:180
bool forEachLeaf(Callable &&func) const
Definition: radix.h:143
bool insert(const RCUPtr< T > &value)
Insert a value into the tree.
Definition: radix.h:111
A TxId is the identifier of a transaction.
Definition: txid.h:14
Information about a mempool transaction.
Definition: txmempool.h:138
Options struct containing options for constructing a CTxMemPool.
int check_ratio
The ratio used to determine how often sanity checks will run.
ValidationSignals * signals
CFeeRate min_relay_feerate
A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation)
std::chrono::seconds expiry
#define AssertLockNotHeld(cs)
Definition: sync.h:163
#define LOCK(cs)
Definition: sync.h:306
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:357
#define NO_THREAD_SAFETY_ANALYSIS
Definition: threadsafety.h:58
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
Definition: time.cpp:80
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1202
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:68
bool ContextualCheckTransactionForCurrentBlock(const CBlockIndex &active_chain_tip, const Consensus::Params &params, const CTransaction &tx, TxValidationState &state)
Definition: tx_verify.cpp:72
std::string RemovalReasonToString(const MemPoolRemovalReason &r) noexcept
Definition: txmempool.cpp:1031
static TxMempoolInfo GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it)
Definition: txmempool.cpp:527
MemPoolRemovalReason
Reason why a transaction was removed from the mempool, this is passed to the notification signal.
Definition: txmempool.h:159
@ SIZELIMIT
Removed in size limiting.
@ BLOCK
Removed for block.
@ MANUAL
Manual removal via RPC.
@ EXPIRY
Expired from mempool.
@ AVALANCHE
Removed by avalanche vote.
@ CONFLICT
Removed for conflict with in-block transaction.
@ REORG
Removed for reorganization.
static const uint32_t MEMPOOL_HEIGHT
Fake height value used in Coins to signify they are only in the memory pool(since 0....
Definition: txmempool.h:56
AssertLockHeld(pool.cs)
assert(!tx.IsCoinBase())