31 while (!staged_ancestors.empty()) {
32 const auto stage = staged_ancestors.begin()->get();
34 txiter stageit = mapTx.find(stage->GetTx().GetId());
35 assert(stageit != mapTx.end());
36 setAncestors.insert(stageit);
37 staged_ancestors.erase(staged_ancestors.begin());
40 (*stageit)->GetMemPoolParentsConst();
41 for (
const auto &parent : parents) {
42 txiter parent_it = mapTx.find(parent.get()->GetTx().GetId());
43 assert(parent_it != mapTx.end());
46 if (setAncestors.count(parent_it) == 0) {
47 staged_ancestors.insert(parent);
57 bool fSearchForParents )
const {
61 if (fSearchForParents) {
70 staged_ancestors.insert(**piter);
75 staged_ancestors = entry->GetMemPoolParentsConst();
83 for (
const auto &parent : (*it)->GetMemPoolParentsConst()) {
84 auto parent_it = mapTx.find(parent.get()->GetTx().GetId());
85 assert(parent_it != mapTx.end());
92 (*it)->GetMemPoolChildrenConst();
93 for (
const auto &child : children) {
94 auto updateIt = mapTx.find(child.get()->GetTx().GetId());
95 assert(updateIt != mapTx.end());
101 for (
txiter removeIt : entriesToRemove) {
111 for (
txiter removeIt : entriesToRemove) {
117 : m_check_ratio(opts.check_ratio), m_max_size_bytes{opts.max_size_bytes},
118 m_expiry{opts.expiry}, m_min_relay_feerate{opts.min_relay_feerate},
119 m_dust_relay_feerate{opts.dust_relay_feerate},
120 m_permit_bare_multisig{opts.permit_bare_multisig},
121 m_max_datacarrier_bytes{opts.max_datacarrier_bytes},
122 m_require_standard{opts.require_standard} {
131 return mapNextTx.count(outpoint);
144 entry->SetEntryId(nextEntryId++);
150 entry->UpdateFeeDelta(feeDelta);
155 auto [newit, inserted] = mapTx.insert(entry);
166 cachedInnerUsage += entry->DynamicMemoryUsage();
169 std::set<TxId> setParentTransactions;
171 mapNextTx.insert(std::make_pair(&in.
prevout, &tx));
179 for (
const auto &pit :
GetIterSet(setParentTransactions)) {
186 totalTxSize += entry->GetTxSize();
187 m_total_fee += entry->GetFee();
201 (*it)->GetSharedTx(), reason, mempool_sequence);
204 for (
const CTxIn &txin : (*it)->GetTx().vin) {
205 mapNextTx.erase(txin.prevout);
209 const TxId &txid = (*it)->GetTx().GetId();
214 totalTxSize -= (*it)->GetTxSize();
215 m_total_fee -= (*it)->GetFee();
216 cachedInnerUsage -= (*it)->DynamicMemoryUsage();
233 if (setDescendants.count(entryit) == 0) {
234 stage.insert(entryit);
239 while (!stage.empty()) {
240 txiter it = *stage.begin();
241 setDescendants.insert(it);
242 stage.erase(stage.begin());
245 (*it)->GetMemPoolChildrenConst();
246 for (
const auto &child : children) {
247 txiter childiter = mapTx.find(child.get()->GetTx().GetId());
248 assert(childiter != mapTx.end());
250 if (!setDescendants.count(childiter)) {
251 stage.insert(childiter);
263 if (origit != mapTx.end()) {
264 txToRemove.insert(origit);
271 while (it != mapNextTx.end() &&
272 it->first->GetTxId() == origTx.
GetId()) {
273 txiter nextit = mapTx.find(it->second->GetId());
274 assert(nextit != mapTx.end());
275 txToRemove.insert(nextit);
281 for (
txiter it : txToRemove) {
292 auto it = mapNextTx.find(txin.
prevout);
293 if (it != mapNextTx.end()) {
295 if (txConflict != tx) {
309 lastRollingFeeUpdate =
GetTime();
310 blockSinceLastRollingFeeBump =
true;
318 cachedInnerUsage = 0;
319 lastRollingFeeUpdate =
GetTime();
320 blockSinceLastRollingFeeBump =
false;
321 rollingMinimumFeeRate = 0;
331 int64_t spendheight)
const {
343 "Checking mempool with %u transactions and %u inputs\n",
344 (
unsigned int)mapTx.size(), (
unsigned int)mapNextTx.size());
346 uint64_t checkTotal = 0;
348 uint64_t innerUsage = 0;
354 checkTotal += entry->GetTxSize();
355 check_total_fee += entry->GetFee();
356 innerUsage += entry->DynamicMemoryUsage();
366 if (parentIt != mapTx.end()) {
370 setParentCheck.insert(*parentIt);
373 assert((*parentIt)->GetEntryId() < entry->GetEntryId());
381 auto prevoutNextIt = mapNextTx.find(txin.
prevout);
382 assert(prevoutNextIt != mapNextTx.end());
384 assert(prevoutNextIt->second == &tx);
386 auto comp = [](
const auto &a,
const auto &b) ->
bool {
387 return a.get()->GetTx().GetId() == b.get()->GetTx().GetId();
389 assert(setParentCheck.size() == entry->GetMemPoolParentsConst().size());
390 assert(std::equal(setParentCheck.begin(), setParentCheck.end(),
391 entry->GetMemPoolParentsConst().begin(), comp));
401 for (
const auto &ancestor : setAncestors) {
402 assert((*ancestor)->GetEntryId() < entry->GetEntryId());
407 auto iter = mapNextTx.lower_bound(
COutPoint(entry->GetTx().GetId(), 0));
408 for (; iter != mapNextTx.end() &&
409 iter->first->GetTxId() == entry->GetTx().GetId();
411 txiter childIt = mapTx.find(iter->second->GetId());
413 assert(childIt != mapTx.end());
414 setChildrenCheck.insert(*childIt);
416 assert(setChildrenCheck.size() ==
417 entry->GetMemPoolChildrenConst().size());
418 assert(std::equal(setChildrenCheck.begin(), setChildrenCheck.end(),
419 entry->GetMemPoolChildrenConst().begin(), comp));
426 spendheight, txfee));
427 for (
const auto &input : tx.
vin) {
428 mempoolDuplicate.SpendCoin(input.prevout);
430 AddCoins(mempoolDuplicate, tx, std::numeric_limits<int>::max());
433 for (
auto &[
_, nextTx] : mapNextTx) {
434 txiter it = mapTx.find(nextTx->GetId());
435 assert(it != mapTx.end());
436 assert(&(*it)->GetTx() == nextTx);
439 assert(totalTxSize == checkTotal);
440 assert(m_total_fee == check_total_fee);
441 assert(innerUsage == cachedInnerUsage);
445 const TxId &txidb)
const {
447 auto it1 = mapTx.find(txida);
448 if (it1 == mapTx.end()) {
451 auto it2 = mapTx.find(txidb);
452 if (it2 == mapTx.end()) {
455 return (*it1)->GetEntryId() < (*it2)->GetEntryId();
462 vtxid.reserve(mapTx.size());
465 vtxid.push_back(entry->GetTx().GetId());
470 GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it) {
472 (*it)->GetFee(), (*it)->GetTxSize(),
473 (*it)->GetModifiedFee() - (*it)->GetFee()};
479 std::vector<TxMempoolInfo> ret;
480 ret.reserve(mapTx.size());
482 const auto &index = mapTx.get<
entry_id>();
483 for (
auto it = index.begin(); it != index.end(); ++it) {
484 ret.push_back(
GetInfo(mapTx.project<0>(it)));
492 indexed_transaction_set::const_iterator i = mapTx.find(txid);
493 if (i == mapTx.end()) {
497 return (*i)->GetSharedTx();
502 indexed_transaction_set::const_iterator i = mapTx.find(txid);
503 if (i == mapTx.end()) {
524 Amount &delta = mapDeltas[txid];
526 txiter it = mapTx.find(txid);
527 if (it != mapTx.end()) {
529 e->UpdateFeeDelta(delta);
540 std::map<TxId, Amount>::const_iterator pos = mapDeltas.find(txid);
541 if (pos == mapDeltas.end()) {
545 nFeeDelta += pos->second;
550 mapDeltas.erase(txid);
554 const auto it = mapNextTx.find(prevout);
555 return it == mapNextTx.end() ? nullptr : it->second;
559 auto it = mapTx.find(txid);
560 if (it != mapTx.end()) {
569 for (
const auto &txid : txids) {
606 if (outpoint.
GetN() < ptx->vout.size()) {
616 for (uint32_t n = 0; n < tx->vout.size(); ++n) {
627 12 *
sizeof(
void *)) *
636 if (m_unbroadcast_txids.erase(txid)) {
640 (unchecked ?
" before confirmation that txn was sent out" :
""));
651 for (
txiter it : stageRevTopo) {
658 indexed_transaction_set::index<entry_time>::type::iterator it =
661 while (it != mapTx.get<
entry_time>().end() && (*it)->GetTime() < time) {
662 toremove.insert(mapTx.project<0>(it));
667 for (
txiter removeit : toremove) {
681 "Expired %i transactions from the memory pool\n", expired);
684 std::vector<COutPoint> vNoSpendsRemaining;
686 for (
const COutPoint &removed : vNoSpendsRemaining) {
694 if (add && (*entry)->GetMemPoolChildren().insert(*child).second) {
696 }
else if (!add && (*entry)->GetMemPoolChildren().erase(*child)) {
704 if (add && (*entry)->GetMemPoolParents().insert(*parent).second) {
706 }
else if (!add && (*entry)->GetMemPoolParents().erase(*parent)) {
713 if (!blockSinceLastRollingFeeBump || rollingMinimumFeeRate == 0) {
718 if (time > lastRollingFeeUpdate + 10) {
726 rollingMinimumFeeRate =
727 rollingMinimumFeeRate /
728 pow(2.0, (time - lastRollingFeeUpdate) / halflife);
729 lastRollingFeeUpdate = time;
738 blockSinceLastRollingFeeBump =
false;
743 std::vector<COutPoint> *pvNoSpendsRemaining) {
746 unsigned nTxnRemoved = 0;
757 CFeeRate removed = (*it)->GetModifiedFeeRate();
761 maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed);
765 nTxnRemoved += stage.size();
767 if (pvNoSpendsRemaining) {
768 for (
const txiter &iter : stage) {
769 for (
const CTxIn &txin : (*iter)->GetTx().vin) {
771 pvNoSpendsRemaining->push_back(txin.
prevout);
782 "Removed %u txn, rolling minimum fee bumped to %s\n",
783 nTxnRemoved, maxFeeRateRemoved.
ToString());
794 m_load_tried = load_tried;
static constexpr Amount SATOSHI
CCoinsView backed by another CCoinsView.
CCoinsView that adds a memory cache for transactions to another CCoinsView.
void Uncache(const COutPoint &outpoint)
Removes the UTXO with the given outpoint from the cache, if it is not modified.
Abstract view on the open txout dataset.
virtual bool GetCoin(const COutPoint &outpoint, Coin &coin) const
Retrieve the Coin (unspent transaction output) for a given outpoint.
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
std::unordered_map< COutPoint, Coin, SaltedOutpointHasher > m_temp_added
Coins made available by transactions being validated.
CCoinsViewMemPool(CCoinsView *baseIn, const CTxMemPool &mempoolIn)
void PackageAddTransaction(const CTransactionRef &tx)
Add the coins created by this transaction.
const CTxMemPool & mempool
Fee rate in satoshis per kilobyte: Amount / kB.
std::string ToString() const
Amount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
void TransactionRemovedFromMempool(const CTransactionRef &, MemPoolRemovalReason, uint64_t mempool_sequence)
An outpoint - a combination of a transaction hash and an index n into its vout.
const TxId & GetTxId() const
The basic transaction that is broadcasted on the network and contained in blocks.
const std::vector< CTxOut > vout
const std::vector< CTxIn > vin
An input of a transaction.
CTxMemPoolEntry stores data about the corresponding transaction, as well as data about all in-mempool...
std::set< std::reference_wrapper< const CTxMemPoolEntryRef >, CompareIteratorById > Children
std::set< std::reference_wrapper< const CTxMemPoolEntryRef >, CompareIteratorById > Parents
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
void removeConflicts(const CTransaction &tx) EXCLUSIVE_LOCKS_REQUIRED(cs)
CFeeRate estimateFee() const
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...
void ClearPrioritisation(const TxId &txid) EXCLUSIVE_LOCKS_REQUIRED(cs)
std::set< txiter, CompareIteratorById > setEntries
void RemoveUnbroadcastTx(const TxId &txid, const bool unchecked=false)
Removes a transaction from the unbroadcast set.
bool GetLoadTried() const
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...
void updateFeeForBlock() EXCLUSIVE_LOCKS_REQUIRED(cs)
Called when a block is connected.
CFeeRate GetMinFee() const
The minimum fee to get into the mempool, which may itself not be enough for larger-sized transactions...
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
void trackPackageRemoved(const CFeeRate &rate) EXCLUSIVE_LOCKS_REQUIRED(cs)
void removeRecursive(const CTransaction &tx, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
void UpdateForRemoveFromMempool(const setEntries &entriesToRemove) EXCLUSIVE_LOCKS_REQUIRED(cs)
For each transaction being removed, update ancestors and any direct children.
const int m_check_ratio
Value n means that 1 times in n we check.
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.
const std::chrono::seconds m_expiry
void AddTransactionsUpdated(unsigned int n)
void UpdateChildrenForRemoval(txiter entry) EXCLUSIVE_LOCKS_REQUIRED(cs)
Sever link between specified transaction and direct children.
bool CompareTopologically(const TxId &txida, const TxId &txidb) const
TxMempoolInfo info(const TxId &txid) const
const int64_t m_max_size_bytes
void getAllTxIds(std::vector< TxId > &vtxid) const
std::atomic< uint32_t > nTransactionsUpdated
Used by getblocktemplate to trigger CreateNewBlock() invocation.
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.
size_t DynamicMemoryUsage() const
std::vector< TxMempoolInfo > infoAll() const
void LimitSize(CCoinsViewCache &coins_cache) EXCLUSIVE_LOCKS_REQUIRED(cs
Reduce the size of the mempool by expiring and then trimming the mempool.
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.
std::set< txiter, CompareIteratorByRevEntryId > setRevTopoEntries
bool exists(const TxId &txid) const
static const int ROLLING_FEE_HALFLIFE
CTransactionRef get(const TxId &txid) const
const CFeeRate m_min_relay_feerate
void PrioritiseTransaction(const TxId &txid, const Amount nFeeDelta)
Affect CreateNewBlock prioritisation of transactions.
indexed_transaction_set::nth_index< 0 >::type::const_iterator txiter
uint64_t GetAndIncrementSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs)
Guards this internal counter for external reporting.
void UpdateChild(txiter entry, txiter child, bool add) EXCLUSIVE_LOCKS_REQUIRED(cs)
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...
RadixTree< CTxMemPoolEntry, MemPoolEntryRadixTreeAdapter > finalizedTxs
CTxMemPool(const Options &opts)
Create a new CTxMemPool.
const CTransaction * GetConflictTx(const COutPoint &prevout) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Get the transaction in the pool that spends the same prevout.
bool CalculateMemPoolAncestors(const CTxMemPoolEntryRef &entry, setEntries &setAncestors, bool fSearchForParents=true) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Try to calculate all in-mempool ancestors of entry.
void CalculateDescendants(txiter it, setEntries &setDescendants) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Populate setDescendants with all in-mempool descendants of hash.
void RemoveStaged(const setEntries &stage, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
Remove a set of transactions from the mempool.
void UpdateParentsOf(bool add, txiter it) EXCLUSIVE_LOCKS_REQUIRED(cs)
Update parents of it to add/remove it as a child transaction.
void ApplyDelta(const TxId &txid, Amount &nFeeDelta) const EXCLUSIVE_LOCKS_REQUIRED(cs)
void SetLoadTried(bool load_tried)
Set whether or not we've made an attempt to load the mempool (regardless of whether the attempt was s...
std::optional< txiter > GetIter(const TxId &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Returns an iterator to the given txid, if found.
void check(const CCoinsViewCache &active_coins_tip, int64_t spendheight) const EXCLUSIVE_LOCKS_REQUIRED(void cs_main
bool isSpent(const COutPoint &outpoint) const
unsigned int GetTransactionsUpdated() const
void _clear() EXCLUSIVE_LOCKS_REQUIRED(cs)
T * get()
Get allows to access the undelying pointer.
std::string ToString() const
std::string GetHex() const
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.
#define LogPrint(category,...)
std::string FormatMoney(const Amount amt)
Do not use these functions to represent or parse monetary amounts to or from JSON but use AmountFromV...
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).
static size_t DynamicUsage(const int8_t &v)
Dynamic memory usage for built-in types is zero.
static size_t IncrementalDynamicUsage(const std::set< X, Y > &s)
static size_t MallocUsage(size_t alloc)
Compute the total memory used by allocating alloc bytes.
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
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
static constexpr Amount zero() noexcept
RCUPtr< T > remove(const KeyType &key)
Remove an element from the tree.
A TxId is the identifier of a transaction.
Information about a mempool transaction.
Options struct containing options for constructing a CTxMemPool.
bilingual_str _(const char *psz)
Translation function.
static TxMempoolInfo GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it)
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.
static const uint32_t MEMPOOL_HEIGHT
Fake height value used in Coins to signify they are only in the memory pool(since 0....
CMainSignals & GetMainSignals()