32 #include <string_view>
53 const std::set<uint256>& setExclude, std::set<uint256>& descendants_to_remove)
56 stageEntries = updateIt->GetMemPoolChildrenConst();
58 while (!stageEntries.empty()) {
60 descendants.insert(descendant);
61 stageEntries.erase(descendant);
64 cacheMap::iterator cacheIt = cachedDescendants.find(mapTx.iterator_to(childEntry));
65 if (cacheIt != cachedDescendants.end()) {
68 for (
txiter cacheEntry : cacheIt->second) {
69 descendants.insert(*cacheEntry);
71 }
else if (!descendants.count(childEntry)) {
73 stageEntries.insert(childEntry);
79 int32_t modifySize = 0;
81 int64_t modifyCount = 0;
83 if (!setExclude.count(descendant.GetTx().GetHash())) {
84 modifySize += descendant.GetTxSize();
85 modifyFee += descendant.GetModifiedFee();
87 cachedDescendants[updateIt].insert(mapTx.iterator_to(descendant));
90 e.UpdateAncestorState(updateIt->GetTxSize(), updateIt->GetModifiedFee(), 1, updateIt->GetSigOpCost());
96 descendants_to_remove.insert(descendant.GetTx().GetHash());
109 cacheMap mapMemPoolDescendantsToUpdate;
113 std::set<uint256> setAlreadyIncluded(vHashesToUpdate.begin(), vHashesToUpdate.end());
115 std::set<uint256> descendants_to_remove;
125 if (
it == mapTx.end()) {
134 for (; iter != mapNextTx.end() && iter->first->hash == hash; ++iter) {
135 const uint256 &childHash = iter->second->GetHash();
136 txiter childIter = mapTx.find(childHash);
137 assert(childIter != mapTx.end());
140 if (!
visited(childIter) && !setAlreadyIncluded.count(childHash)) {
149 for (
const auto& txid : descendants_to_remove) {
162 const Limits& limits)
const
164 int64_t totalSizeWithAncestors = entry_size;
167 while (!staged_ancestors.empty()) {
169 txiter stageit = mapTx.iterator_to(stage);
171 ancestors.insert(stageit);
172 staged_ancestors.erase(stage);
173 totalSizeWithAncestors += stageit->
GetTxSize();
177 }
else if (stageit->GetCountWithDescendants() + entry_count >
static_cast<uint64_t
>(limits.
descendant_count)) {
185 txiter parent_it = mapTx.iterator_to(parent);
188 if (ancestors.count(parent_it) == 0) {
189 staged_ancestors.insert(parent);
191 if (staged_ancestors.size() + ancestors.size() + entry_count >
static_cast<uint64_t
>(limits.
ancestor_count)) {
201 const int64_t total_vsize)
const
203 size_t pack_count = package.size();
217 for (
const auto& tx : package) {
218 for (
const auto& input : tx->vin) {
219 std::optional<txiter> piter =
GetIter(input.prevout.hash);
221 staged_ancestors.insert(**piter);
241 bool fSearchForParents )
const
246 if (fSearchForParents) {
250 for (
unsigned int i = 0; i < tx.
vin.size(); i++) {
251 std::optional<txiter> piter =
GetIter(tx.
vin[i].prevout.hash);
253 staged_ancestors.insert(**piter);
254 if (staged_ancestors.size() + 1 >
static_cast<uint64_t
>(limits.
ancestor_count)) {
262 txiter it = mapTx.iterator_to(entry);
263 staged_ancestors =
it->GetMemPoolParentsConst();
271 std::string_view calling_fn_name,
274 bool fSearchForParents )
const
291 const int32_t updateCount = (add ? 1 : -1);
292 const int32_t updateSize{updateCount *
it->GetTxSize()};
293 const CAmount updateFee = updateCount *
it->GetModifiedFee();
294 for (
txiter ancestorIt : setAncestors) {
301 int64_t updateCount = setAncestors.size();
302 int64_t updateSize = 0;
304 int64_t updateSigOpsCost = 0;
305 for (
txiter ancestorIt : setAncestors) {
306 updateSize += ancestorIt->GetTxSize();
307 updateFee += ancestorIt->GetModifiedFee();
308 updateSigOpsCost += ancestorIt->GetSigOpCost();
325 if (updateDescendants) {
332 for (
txiter removeIt : entriesToRemove) {
335 setDescendants.erase(removeIt);
336 int32_t modifySize = -removeIt->GetTxSize();
337 CAmount modifyFee = -removeIt->GetModifiedFee();
338 int modifySigOps = -removeIt->GetSigOpCost();
339 for (
txiter dit : setDescendants) {
344 for (
txiter removeIt : entriesToRemove) {
373 for (
txiter removeIt : entriesToRemove) {
399 : m_check_ratio{opts.check_ratio},
400 m_max_size_bytes{opts.max_size_bytes},
401 m_expiry{opts.expiry},
402 m_incremental_relay_feerate{opts.incremental_relay_feerate},
403 m_min_relay_feerate{opts.min_relay_feerate},
404 m_dust_relay_feerate{opts.dust_relay_feerate},
405 m_permit_bare_multisig{opts.permit_bare_multisig},
406 m_max_datacarrier_bytes{opts.max_datacarrier_bytes},
407 m_require_standard{opts.require_standard},
408 m_full_rbf{opts.full_rbf},
409 m_persist_v1_dat{opts.persist_v1_dat},
410 m_limits{opts.limits},
418 return mapNextTx.count(outpoint);
453 std::set<Txid> setParentTransactions;
454 for (
unsigned int i = 0; i < tx.
vin.size(); i++) {
455 mapNextTx.insert(std::make_pair(&tx.
vin[i].prevout, &tx));
456 setParentTransactions.insert(tx.
vin[i].prevout.hash);
466 for (
const auto& pit :
GetIterSet(setParentTransactions)) {
474 m_total_fee += entry.
GetFee();
476 txns_randomized.emplace_back(newit->GetSharedTx());
477 newit->idx_randomized = txns_randomized.size() - 1;
500 it->GetTx().GetHash().data(),
504 std::chrono::duration_cast<std::chrono::duration<std::uint64_t>>(
it->GetTime()).count()
507 for (
const CTxIn& txin :
it->GetTx().vin)
508 mapNextTx.erase(txin.prevout);
512 if (txns_randomized.size() > 1) {
514 Assert(
GetEntry(txns_randomized.back()->GetHash()))->idx_randomized =
it->idx_randomized;
516 txns_randomized[
it->idx_randomized] = std::move(txns_randomized.back());
517 txns_randomized.pop_back();
518 if (txns_randomized.size() * 2 < txns_randomized.capacity())
519 txns_randomized.shrink_to_fit();
521 txns_randomized.clear();
523 totalTxSize -=
it->GetTxSize();
524 m_total_fee -=
it->GetFee();
525 cachedInnerUsage -=
it->DynamicMemoryUsage();
540 if (setDescendants.count(entryit) == 0) {
541 stage.insert(entryit);
546 while (!stage.empty()) {
548 setDescendants.insert(
it);
553 txiter childiter = mapTx.iterator_to(child);
554 if (!setDescendants.count(childiter)) {
555 stage.insert(childiter);
567 if (origit != mapTx.end()) {
568 txToRemove.insert(origit);
574 for (
unsigned int i = 0; i < origTx.
vout.size(); i++) {
576 if (
it == mapNextTx.end())
578 txiter nextit = mapTx.find(
it->second->GetHash());
579 assert(nextit != mapTx.end());
580 txToRemove.insert(nextit);
598 for (indexed_transaction_set::const_iterator
it = mapTx.begin();
it != mapTx.end();
it++) {
599 if (check_final_and_mature(
it)) txToRemove.insert(
it);
606 for (indexed_transaction_set::const_iterator
it = mapTx.begin();
it != mapTx.end();
it++) {
617 if (
it != mapNextTx.end()) {
619 if (txConflict != tx)
634 std::vector<RemovedMempoolTransactionInfo> txs_removed_for_block;
635 txs_removed_for_block.reserve(vtx.size());
636 for (
const auto& tx : vtx)
639 if (
it != mapTx.end()) {
642 txs_removed_for_block.emplace_back(*
it);
651 lastRollingFeeUpdate =
GetTime();
652 blockSinceLastRollingFeeBump =
true;
655 void CTxMemPool::check(
const CCoinsViewCache& active_coins_tip, int64_t spendheight)
const
663 LogPrint(
BCLog::MEMPOOL,
"Checking mempool with %u transactions and %u inputs\n", (
unsigned int)mapTx.size(), (
unsigned int)mapNextTx.size());
665 uint64_t checkTotal = 0;
667 uint64_t innerUsage = 0;
668 uint64_t prev_ancestor_count{0};
673 checkTotal +=
it->GetTxSize();
674 check_total_fee +=
it->GetFee();
675 innerUsage +=
it->DynamicMemoryUsage();
681 indexed_transaction_set::const_iterator it2 = mapTx.find(txin.
prevout.
hash);
682 if (it2 != mapTx.end()) {
685 setParentCheck.insert(*it2);
692 auto it3 = mapNextTx.find(txin.
prevout);
693 assert(it3 != mapNextTx.end());
695 assert(it3->second == &tx);
700 assert(setParentCheck.size() ==
it->GetMemPoolParentsConst().size());
701 assert(std::equal(setParentCheck.begin(), setParentCheck.end(),
it->GetMemPoolParentsConst().begin(), comp));
704 uint64_t nCountCheck = ancestors.size() + 1;
705 int32_t nSizeCheck =
it->GetTxSize();
706 CAmount nFeesCheck =
it->GetModifiedFee();
707 int64_t nSigOpCheck =
it->GetSigOpCost();
709 for (
txiter ancestorIt : ancestors) {
710 nSizeCheck += ancestorIt->GetTxSize();
711 nFeesCheck += ancestorIt->GetModifiedFee();
712 nSigOpCheck += ancestorIt->GetSigOpCost();
715 assert(
it->GetCountWithAncestors() == nCountCheck);
716 assert(
it->GetSizeWithAncestors() == nSizeCheck);
717 assert(
it->GetSigOpCostWithAncestors() == nSigOpCheck);
718 assert(
it->GetModFeesWithAncestors() == nFeesCheck);
720 assert(prev_ancestor_count <= it->GetCountWithAncestors());
721 prev_ancestor_count =
it->GetCountWithAncestors();
725 auto iter = mapNextTx.lower_bound(
COutPoint(
it->GetTx().GetHash(), 0));
726 int32_t child_sizes{0};
727 for (; iter != mapNextTx.end() && iter->first->hash ==
it->GetTx().GetHash(); ++iter) {
728 txiter childit = mapTx.find(iter->second->GetHash());
729 assert(childit != mapTx.end());
730 if (setChildrenCheck.insert(*childit).second) {
731 child_sizes += childit->GetTxSize();
734 assert(setChildrenCheck.size() ==
it->GetMemPoolChildrenConst().size());
735 assert(std::equal(setChildrenCheck.begin(), setChildrenCheck.end(),
it->GetMemPoolChildrenConst().begin(), comp));
738 assert(
it->GetSizeWithDescendants() >= child_sizes +
it->GetTxSize());
744 for (
const auto& input: tx.
vin) mempoolDuplicate.SpendCoin(input.prevout);
745 AddCoins(mempoolDuplicate, tx, std::numeric_limits<int>::max());
747 for (
auto it = mapNextTx.cbegin();
it != mapNextTx.cend();
it++) {
749 indexed_transaction_set::const_iterator it2 = mapTx.find(hash);
751 assert(it2 != mapTx.end());
755 assert(totalTxSize == checkTotal);
756 assert(m_total_fee == check_total_fee);
757 assert(innerUsage == cachedInnerUsage);
768 indexed_transaction_set::const_iterator j = wtxid ?
get_iter_from_wtxid(hashb) : mapTx.find(hashb);
769 if (j == mapTx.end())
return false;
770 indexed_transaction_set::const_iterator i = wtxid ?
get_iter_from_wtxid(hasha) : mapTx.find(hasha);
771 if (i == mapTx.end())
return true;
772 uint64_t counta = i->GetCountWithAncestors();
773 uint64_t countb = j->GetCountWithAncestors();
774 if (counta == countb) {
777 return counta < countb;
781 class DepthAndScoreComparator
784 bool operator()(
const CTxMemPool::indexed_transaction_set::const_iterator& a,
const CTxMemPool::indexed_transaction_set::const_iterator& b)
786 uint64_t counta = a->GetCountWithAncestors();
787 uint64_t countb = b->GetCountWithAncestors();
788 if (counta == countb) {
791 return counta < countb;
798 std::vector<indexed_transaction_set::const_iterator> iters;
801 iters.reserve(mapTx.size());
803 for (indexed_transaction_set::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi) {
806 std::sort(iters.begin(), iters.end(), DepthAndScoreComparator());
811 return TxMempoolInfo{it->GetSharedTx(), it->GetTime(), it->GetFee(), it->GetTxSize(), it->GetModifiedFee() - it->GetFee()};
818 std::vector<CTxMemPoolEntryRef>
ret;
819 ret.reserve(mapTx.size());
821 ret.emplace_back(*
it);
831 std::vector<TxMempoolInfo>
ret;
832 ret.reserve(mapTx.size());
833 for (
auto it : iters) {
843 const auto i = mapTx.find(txid);
844 return i == mapTx.end() ? nullptr : &(*i);
850 indexed_transaction_set::const_iterator i = mapTx.find(hash);
851 if (i == mapTx.end())
853 return i->GetSharedTx();
860 if (i == mapTx.end())
869 if (i != mapTx.end() && i->GetSequence() < last_sequence) {
880 CAmount &delta = mapDeltas[hash];
883 if (
it != mapTx.end()) {
887 for (
txiter ancestorIt : ancestors) {
893 setDescendants.erase(
it);
894 for (
txiter descendantIt : setDescendants) {
900 mapDeltas.erase(hash);
901 LogPrintf(
"PrioritiseTransaction: %s (%sin mempool) delta cleared\n", hash.
ToString(),
it == mapTx.end() ?
"not " :
"");
903 LogPrintf(
"PrioritiseTransaction: %s (%sin mempool) fee += %s, new delta=%s\n",
905 it == mapTx.end() ?
"not " :
"",
915 std::map<uint256, CAmount>::const_iterator pos = mapDeltas.find(hash);
916 if (pos == mapDeltas.end())
918 const CAmount &delta = pos->second;
925 mapDeltas.erase(hash);
932 std::vector<delta_info> result;
933 result.reserve(mapDeltas.size());
934 for (
const auto& [txid, delta] : mapDeltas) {
935 const auto iter{mapTx.find(txid)};
936 const bool in_mempool{iter != mapTx.end()};
937 std::optional<CAmount> modified_fee;
938 if (in_mempool) modified_fee = iter->GetModifiedFee();
939 result.emplace_back(
delta_info{in_mempool, delta, modified_fee, txid});
946 const auto it = mapNextTx.find(prevout);
947 return it == mapNextTx.end() ? nullptr :
it->second;
952 auto it = mapTx.find(txid);
953 if (
it != mapTx.end())
return it;
960 for (
const auto& h : hashes) {
962 if (mi)
ret.insert(*mi);
970 std::vector<txiter>
ret;
971 ret.reserve(txids.size());
972 for (
const auto& txid : txids) {
982 for (
unsigned int i = 0; i < tx.
vin.size(); i++)
1003 if (outpoint.
n < ptx->vout.size()) {
1016 for (
unsigned int n = 0; n < tx->vout.size(); ++n) {
1036 if (m_unbroadcast_txids.erase(txid))
1038 LogPrint(
BCLog::MEMPOOL,
"Removed %i from set of unbroadcast txns%s\n", txid.
GetHex(), (unchecked ?
" before confirmation that txn was sent out" :
""));
1053 indexed_transaction_set::index<entry_time>::type::iterator
it = mapTx.get<
entry_time>().begin();
1055 while (
it != mapTx.get<
entry_time>().end() &&
it->GetTime() < time) {
1056 toremove.insert(mapTx.project<0>(
it));
1060 for (
txiter removeit : toremove) {
1064 return stage.size();
1077 if (add && entry->GetMemPoolChildren().insert(*child).second) {
1079 }
else if (!add && entry->GetMemPoolChildren().erase(*child)) {
1088 if (add && entry->GetMemPoolParents().insert(*parent).second) {
1090 }
else if (!add && entry->GetMemPoolParents().erase(*parent)) {
1097 if (!blockSinceLastRollingFeeBump || rollingMinimumFeeRate == 0)
1098 return CFeeRate(llround(rollingMinimumFeeRate));
1101 if (time > lastRollingFeeUpdate + 10) {
1108 rollingMinimumFeeRate = rollingMinimumFeeRate / pow(2.0, (time - lastRollingFeeUpdate) / halflife);
1109 lastRollingFeeUpdate = time;
1112 rollingMinimumFeeRate = 0;
1121 if (rate.
GetFeePerK() > rollingMinimumFeeRate) {
1123 blockSinceLastRollingFeeBump =
false;
1130 unsigned nTxnRemoved = 0;
1133 indexed_transaction_set::index<descendant_score>::type::iterator
it = mapTx.get<
descendant_score>().begin();
1139 CFeeRate removed(
it->GetModFeesWithDescendants(),
it->GetSizeWithDescendants());
1142 maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed);
1146 nTxnRemoved += stage.size();
1148 std::vector<CTransaction> txn;
1149 if (pvNoSpendsRemaining) {
1150 txn.reserve(stage.size());
1151 for (
txiter iter : stage)
1152 txn.push_back(iter->GetTx());
1155 if (pvNoSpendsRemaining) {
1159 pvNoSpendsRemaining->push_back(txin.
prevout);
1165 if (maxFeeRateRemoved >
CFeeRate(0)) {
1172 std::vector<txiter> candidates;
1174 candidates.push_back(entry);
1175 uint64_t maximum = 0;
1176 while (candidates.size()) {
1177 txiter candidate = candidates.back();
1178 candidates.pop_back();
1179 if (!counted.insert(candidate).second)
continue;
1181 if (parents.size() == 0) {
1182 maximum = std::max(maximum, candidate->GetCountWithDescendants());
1185 candidates.push_back(mapTx.iterator_to(i));
1194 auto it = mapTx.find(txid);
1195 ancestors = descendants = 0;
1196 if (
it != mapTx.end()) {
1197 ancestors =
it->GetCountWithAncestors();
1198 if (ancestorsize) *ancestorsize =
it->GetSizeWithAncestors();
1199 if (ancestorfees) *ancestorfees =
it->GetModFeesWithAncestors();
1207 return m_load_tried;
1213 m_load_tried = load_tried;
1219 std::vector<txiter> clustered_txs{
GetIterVec(txids)};
1223 for (
const auto&
it : clustered_txs) {
1227 for (
size_t i{0}; i < clustered_txs.size(); ++i) {
1229 if (clustered_txs.size() > 500)
return {};
1230 const txiter& tx_iter = clustered_txs.at(i);
1231 for (
const auto& entries : {tx_iter->GetMemPoolParentsConst(), tx_iter->GetMemPoolChildrenConst()}) {
1233 const auto entry_it = mapTx.iterator_to(entry);
1235 clustered_txs.push_back(entry_it);
1240 return clustered_txs;
1245 for (
const auto& direct_conflict : direct_conflicts) {
1247 const auto ancestor_count{direct_conflict->GetCountWithAncestors()};
1248 const auto descendant_count{direct_conflict->GetCountWithDescendants()};
1249 const bool has_ancestor{ancestor_count > 1};
1250 const bool has_descendant{descendant_count > 1};
1251 const auto& txid_string{direct_conflict->GetSharedTx()->GetHash().ToString()};
1256 if (ancestor_count > 2) {
1257 return strprintf(
"%s has %u ancestors, max 1 allowed", txid_string, ancestor_count - 1);
1258 }
else if (descendant_count > 2) {
1259 return strprintf(
"%s has %u descendants, max 1 allowed", txid_string, descendant_count - 1);
1260 }
else if (has_ancestor && has_descendant) {
1261 return strprintf(
"%s has both ancestor and descendant, exceeding cluster limit of 2", txid_string);
1266 if (has_descendant) {
1267 const auto& our_child = direct_conflict->GetMemPoolChildrenConst().begin();
1268 if (our_child->get().GetCountWithAncestors() > 2) {
1269 return strprintf(
"%s is not the only parent of child %s",
1270 txid_string, our_child->get().GetSharedTx()->GetHash().ToString());
1272 }
else if (has_ancestor) {
1273 const auto& our_parent = direct_conflict->GetMemPoolParentsConst().begin();
1274 if (our_parent->get().GetCountWithDescendants() > 2) {
1275 return strprintf(
"%s is not the only child of parent %s",
1276 txid_string, our_parent->get().GetSharedTx()->GetHash().ToString());
1280 return std::nullopt;
1285 Assume(replacement_vsize > 0);
1288 if (err_string.has_value()) {
1301 std::vector<FeeFrac> old_chunks;
1308 for (
auto txiter : all_conflicts) {
1310 if (
txiter->GetCountWithDescendants() > 1) {
1316 if (
txiter->GetCountWithAncestors() > 1) {
1319 FeeFrac package{
txiter->GetModFeesWithAncestors(),
static_cast<int32_t
>(
txiter->GetSizeWithAncestors())};
1320 if (individual > package) {
1324 old_chunks.emplace_back(package);
1327 old_chunks.emplace_back(package - individual);
1328 old_chunks.emplace_back(individual);
1331 old_chunks.emplace_back(individual);
1336 std::sort(old_chunks.begin(), old_chunks.end(), std::greater());
1339 std::vector<FeeFrac> new_chunks;
1349 for (
auto direct_conflict : direct_conflicts) {
1352 if (direct_conflict->GetMemPoolParentsConst().size() > 0) {
1355 if (!all_conflicts.count(mapTx.iterator_to(parent))) {
1363 new_chunks.emplace_back(replacement_fees, int32_t(replacement_vsize));
1366 std::sort(new_chunks.begin(), new_chunks.end(), std::greater());
1368 return std::make_pair(old_diagram, new_diagram);
int64_t CAmount
Amount in satoshis (Can be negative)
#define Assert(val)
Identity function.
#define Assume(val)
Assume is the identity function.
An in-memory indexed chain of blocks.
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
CCoinsView backed by another CCoinsView.
CCoinsView that adds a memory cache for transactions to another CCoinsView.
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
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.
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...
void PackageAddTransaction(const CTransactionRef &tx)
Add the coins created by this transaction.
const CTxMemPool & mempool
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
std::string ToString(const FeeEstimateMode &fee_estimate_mode=FeeEstimateMode::BTC_KVB) const
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
An outpoint - a combination of a transaction hash and an index n into its vout.
The basic transaction that is broadcasted on the network and contained in blocks.
const Txid & GetHash() const LIFETIMEBOUND
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...
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
const Parents & GetMemPoolParentsConst() const
CAmount nModFeesWithAncestors
void UpdateModifiedFee(CAmount fee_diff)
size_t DynamicMemoryUsage() const
std::set< CTxMemPoolEntryRef, CompareIteratorByHash > Children
CAmount nModFeesWithDescendants
... and total fees (all including us)
int32_t GetTxSize() const
int64_t nSizeWithDescendants
... and size
int64_t m_count_with_ancestors
void UpdateDescendantState(int32_t modifySize, CAmount modifyFee, int64_t modifyCount)
CAmount GetModifiedFee() const
const CAmount & GetFee() const
static constexpr ExplicitCopyTag ExplicitCopy
int64_t nSizeWithAncestors
const Children & GetMemPoolChildrenConst() const
std::set< CTxMemPoolEntryRef, CompareIteratorByHash > 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)
std::atomic< unsigned int > nTransactionsUpdated
Used by getblocktemplate to trigger CreateNewBlock() invocation.
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.
ValidationSignals *const m_signals
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...
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
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)
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.
void UpdateTransactionsFromBlock(const std::vector< uint256 > &vHashesToUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs
UpdateTransactionsFromBlock is called when adding transactions from a disconnected block back to the ...
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
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 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)
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 >xid) 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...
static const int ROLLING_FEE_HALFLIFE
std::set< txiter, CompareIteratorByHash > setEntries
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
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)
TxMempoolInfo info_for_relay(const GenTxid >xid, uint64_t last_sequence) const
Returns info for a transaction if its entry_sequence < last_sequence.
bool exists(const GenTxid >xid) const
std::map< txiter, setEntries, CompareIteratorByHash > cacheMap
CTxMemPool(const Options &opts)
Create a new CTxMemPool.
const CFeeRate m_incremental_relay_feerate
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)
util::Result< std::pair< std::vector< FeeFrac >, std::vector< FeeFrac > > > CalculateFeerateDiagramsForRBF(CAmount replacement_fees, int64_t replacement_vsize, const setEntries &direct_conflicts, const setEntries &all_conflicts) EXCLUSIVE_LOCKS_REQUIRED(cs)
Calculate the old and new mempool feerate diagrams relating to the clusters that would be affected by...
void check(const CCoinsViewCache &active_coins_tip, int64_t spendheight) const EXCLUSIVE_LOCKS_REQUIRED(void cs_main
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)
unsigned int GetTransactionsUpdated() const
void check(const CCoinsViewCache &active_coins_tip, int64_t spendheight) const EXCLUSIVE_LOCKS_REQUIRED(void 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...
Sort by feerate of entry (fee/size) in descending order This is only used for transaction relay,...
A generic txid reference (txid or wtxid).
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 ToString() const
std::string GetHex() const
static transaction_identifier FromUint256(const uint256 &id)
constexpr const std::byte * data() 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.
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
#define WITH_FRESH_EPOCH(epoch)
#define LogPrintLevel(category, level,...)
#define LogPrint(category,...)
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.
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.
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.
bilingual_str ErrorString(const Result< T > &result)
ValidationSignals & m_signals
T SaturatingAdd(const T i, const T j) noexcept
std::vector< CTransactionRef > Package
A package is an ordered list of transactions.
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...
reverse_range< T > reverse_iterate(T &x)
Data structure storing a fee and size, ordered by increasing fee/size.
CBlockIndex * maxInputBlock
Information about a mempool transaction.
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.
#define AssertLockNotHeld(cs)
#define TRACE3(context, event, a, b, c)
#define TRACE5(context, event, a, b, c, d, e)
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
bool TestLockPointValidity(CChain &active_chain, const LockPoints &lp)
Test whether the LockPoints height and time are still valid on the current chain.
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....
std::vector< FeeFrac > BuildDiagramFromChunks(const Span< const FeeFrac > chunks)
Takes the pre-computed and topologically-valid chunks and generates a fee diagram which starts at Fee...