34 #include <string_view> 55 const std::set<uint256>& setExclude, std::set<uint256>& descendants_to_remove)
58 stageEntries = updateIt->GetMemPoolChildrenConst();
60 while (!stageEntries.empty()) {
62 descendants.insert(descendant);
63 stageEntries.erase(descendant);
66 cacheMap::iterator cacheIt = cachedDescendants.find(mapTx.iterator_to(childEntry));
67 if (cacheIt != cachedDescendants.end()) {
70 for (
txiter cacheEntry : cacheIt->second) {
71 descendants.insert(*cacheEntry);
73 }
else if (!descendants.count(childEntry)) {
75 stageEntries.insert(childEntry);
81 int32_t modifySize = 0;
83 int64_t modifyCount = 0;
85 if (!setExclude.count(descendant.GetTx().GetHash())) {
86 modifySize += descendant.GetTxSize();
87 modifyFee += descendant.GetModifiedFee();
89 cachedDescendants[updateIt].insert(mapTx.iterator_to(descendant));
92 e.UpdateAncestorState(updateIt->GetTxSize(), updateIt->GetModifiedFee(), 1, updateIt->GetSigOpCost());
98 descendants_to_remove.insert(descendant.GetTx().GetHash());
111 cacheMap mapMemPoolDescendantsToUpdate;
115 std::set<uint256> setAlreadyIncluded(vHashesToUpdate.begin(), vHashesToUpdate.end());
117 std::set<uint256> descendants_to_remove;
124 for (
const uint256& hash : vHashesToUpdate | std::views::reverse) {
127 if (
it == mapTx.end()) {
136 for (; iter != mapNextTx.end() && iter->first->hash == hash; ++iter) {
137 const uint256 &childHash = iter->second->GetHash();
138 txiter childIter = mapTx.find(childHash);
139 assert(childIter != mapTx.end());
142 if (!
visited(childIter) && !setAlreadyIncluded.count(childHash)) {
151 for (
const auto& txid : descendants_to_remove) {
164 const Limits& limits)
const 166 int64_t totalSizeWithAncestors = entry_size;
169 while (!staged_ancestors.empty()) {
171 txiter stageit = mapTx.iterator_to(stage);
173 ancestors.insert(stageit);
174 staged_ancestors.erase(stage);
175 totalSizeWithAncestors += stageit->
GetTxSize();
179 }
else if (stageit->GetCountWithDescendants() + entry_count >
static_cast<uint64_t
>(limits.
descendant_count)) {
187 txiter parent_it = mapTx.iterator_to(parent);
190 if (ancestors.count(parent_it) == 0) {
191 staged_ancestors.insert(parent);
193 if (staged_ancestors.size() + ancestors.size() + entry_count >
static_cast<uint64_t
>(limits.
ancestor_count)) {
203 const int64_t total_vsize)
const 205 size_t pack_count = package.size();
219 for (
const auto& tx : package) {
220 for (
const auto& input : tx->vin) {
221 std::optional<txiter> piter =
GetIter(input.prevout.hash);
223 staged_ancestors.insert(**piter);
243 bool fSearchForParents )
const 248 if (fSearchForParents) {
252 for (
unsigned int i = 0; i < tx.
vin.size(); i++) {
253 std::optional<txiter> piter =
GetIter(tx.
vin[i].prevout.hash);
255 staged_ancestors.insert(**piter);
256 if (staged_ancestors.size() + 1 >
static_cast<uint64_t
>(limits.
ancestor_count)) {
264 txiter it = mapTx.iterator_to(entry);
265 staged_ancestors =
it->GetMemPoolParentsConst();
273 std::string_view calling_fn_name,
276 bool fSearchForParents )
const 293 const int32_t updateCount = (add ? 1 : -1);
294 const int32_t updateSize{updateCount *
it->GetTxSize()};
295 const CAmount updateFee = updateCount *
it->GetModifiedFee();
296 for (
txiter ancestorIt : setAncestors) {
303 int64_t updateCount = setAncestors.size();
304 int64_t updateSize = 0;
306 int64_t updateSigOpsCost = 0;
307 for (
txiter ancestorIt : setAncestors) {
308 updateSize += ancestorIt->GetTxSize();
309 updateFee += ancestorIt->GetModifiedFee();
310 updateSigOpsCost += ancestorIt->GetSigOpCost();
327 if (updateDescendants) {
334 for (
txiter removeIt : entriesToRemove) {
337 setDescendants.erase(removeIt);
338 int32_t modifySize = -removeIt->GetTxSize();
339 CAmount modifyFee = -removeIt->GetModifiedFee();
340 int modifySigOps = -removeIt->GetSigOpCost();
341 for (
txiter dit : setDescendants) {
346 for (
txiter removeIt : entriesToRemove) {
375 for (
txiter removeIt : entriesToRemove) {
403 opts.
check_ratio = std::clamp<int>(opts.check_ratio, 0, 1
'000'000);
404 int64_t descendant_limit_bytes = opts.limits.descendant_size_vbytes * 40;
405 if (opts.max_size_bytes < 0 || opts.max_size_bytes < descendant_limit_bytes) {
406 error =
strprintf(
_(
"-maxmempool must be at least %d MB"), std::ceil(descendant_limit_bytes / 1
'000'000.0));
408 return std::move(opts);
412 : m_opts{
Flatten(std::move(opts), error)}
419 return mapNextTx.count(outpoint);
454 std::set<Txid> setParentTransactions;
455 for (
unsigned int i = 0; i < tx.
vin.size(); i++) {
456 mapNextTx.insert(std::make_pair(&tx.
vin[i].prevout, &tx));
457 setParentTransactions.insert(tx.
vin[i].prevout.hash);
467 for (
const auto& pit :
GetIterSet(setParentTransactions)) {
475 m_total_fee += entry.
GetFee();
477 txns_randomized.emplace_back(newit->GetSharedTx());
478 newit->idx_randomized = txns_randomized.size() - 1;
501 it->GetTx().GetHash().data(),
505 std::chrono::duration_cast<std::chrono::duration<std::uint64_t>>(
it->GetTime()).
count()
508 for (
const CTxIn& txin :
it->GetTx().vin)
509 mapNextTx.erase(txin.prevout);
513 if (txns_randomized.size() > 1) {
515 Assert(
GetEntry(txns_randomized.back()->GetHash()))->idx_randomized =
it->idx_randomized;
517 txns_randomized[
it->idx_randomized] = std::move(txns_randomized.back());
518 txns_randomized.pop_back();
519 if (txns_randomized.size() * 2 < txns_randomized.capacity())
520 txns_randomized.shrink_to_fit();
522 txns_randomized.clear();
524 totalTxSize -=
it->GetTxSize();
525 m_total_fee -=
it->GetFee();
526 cachedInnerUsage -=
it->DynamicMemoryUsage();
541 if (setDescendants.count(entryit) == 0) {
542 stage.insert(entryit);
547 while (!stage.empty()) {
549 setDescendants.insert(
it);
554 txiter childiter = mapTx.iterator_to(child);
555 if (!setDescendants.count(childiter)) {
556 stage.insert(childiter);
568 if (origit != mapTx.end()) {
569 txToRemove.insert(origit);
575 for (
unsigned int i = 0; i < origTx.
vout.size(); i++) {
577 if (
it == mapNextTx.end())
579 txiter nextit = mapTx.find(
it->second->GetHash());
580 assert(nextit != mapTx.end());
581 txToRemove.insert(nextit);
599 for (indexed_transaction_set::const_iterator
it = mapTx.begin();
it != mapTx.end();
it++) {
600 if (check_final_and_mature(
it)) txToRemove.insert(
it);
607 for (indexed_transaction_set::const_iterator
it = mapTx.begin();
it != mapTx.end();
it++) {
618 if (
it != mapNextTx.end()) {
620 if (txConflict != tx)
635 std::vector<RemovedMempoolTransactionInfo> txs_removed_for_block;
636 txs_removed_for_block.reserve(vtx.size());
637 for (
const auto& tx : vtx)
640 if (
it != mapTx.end()) {
643 txs_removed_for_block.emplace_back(*
it);
652 lastRollingFeeUpdate =
GetTime();
653 blockSinceLastRollingFeeBump =
true;
656 void CTxMemPool::check(
const CCoinsViewCache& active_coins_tip, int64_t spendheight)
const 664 LogPrint(
BCLog::MEMPOOL,
"Checking mempool with %u transactions and %u inputs\n", (
unsigned int)mapTx.size(), (
unsigned int)mapNextTx.size());
666 uint64_t checkTotal = 0;
668 uint64_t innerUsage = 0;
669 uint64_t prev_ancestor_count{0};
671 CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(&active_coins_tip));
674 checkTotal +=
it->GetTxSize();
675 check_total_fee +=
it->GetFee();
676 innerUsage +=
it->DynamicMemoryUsage();
682 indexed_transaction_set::const_iterator it2 = mapTx.find(txin.
prevout.
hash);
683 if (it2 != mapTx.end()) {
686 setParentCheck.insert(*it2);
693 auto it3 = mapNextTx.find(txin.
prevout);
694 assert(it3 != mapNextTx.end());
696 assert(it3->second == &tx);
701 assert(setParentCheck.size() ==
it->GetMemPoolParentsConst().size());
702 assert(std::equal(setParentCheck.begin(), setParentCheck.end(),
it->GetMemPoolParentsConst().begin(), comp));
705 uint64_t nCountCheck = ancestors.size() + 1;
706 int32_t nSizeCheck =
it->GetTxSize();
707 CAmount nFeesCheck =
it->GetModifiedFee();
708 int64_t nSigOpCheck =
it->GetSigOpCost();
710 for (
txiter ancestorIt : ancestors) {
711 nSizeCheck += ancestorIt->GetTxSize();
712 nFeesCheck += ancestorIt->GetModifiedFee();
713 nSigOpCheck += ancestorIt->GetSigOpCost();
716 assert(
it->GetCountWithAncestors() == nCountCheck);
717 assert(
it->GetSizeWithAncestors() == nSizeCheck);
718 assert(
it->GetSigOpCostWithAncestors() == nSigOpCheck);
719 assert(
it->GetModFeesWithAncestors() == nFeesCheck);
721 assert(prev_ancestor_count <= it->GetCountWithAncestors());
722 prev_ancestor_count =
it->GetCountWithAncestors();
726 auto iter = mapNextTx.lower_bound(
COutPoint(
it->GetTx().GetHash(), 0));
727 int32_t child_sizes{0};
728 for (; iter != mapNextTx.end() && iter->first->hash ==
it->GetTx().GetHash(); ++iter) {
729 txiter childit = mapTx.find(iter->second->GetHash());
730 assert(childit != mapTx.end());
731 if (setChildrenCheck.insert(*childit).second) {
732 child_sizes += childit->GetTxSize();
735 assert(setChildrenCheck.size() ==
it->GetMemPoolChildrenConst().size());
736 assert(std::equal(setChildrenCheck.begin(), setChildrenCheck.end(),
it->GetMemPoolChildrenConst().begin(), comp));
739 assert(
it->GetSizeWithDescendants() >= child_sizes +
it->GetTxSize());
745 for (
const auto& input: tx.
vin) mempoolDuplicate.SpendCoin(input.prevout);
746 AddCoins(mempoolDuplicate, tx, std::numeric_limits<int>::max());
748 for (
auto it = mapNextTx.cbegin();
it != mapNextTx.cend();
it++) {
750 indexed_transaction_set::const_iterator it2 = mapTx.find(hash);
752 assert(it2 != mapTx.end());
756 assert(totalTxSize == checkTotal);
757 assert(m_total_fee == check_total_fee);
758 assert(innerUsage == cachedInnerUsage);
769 indexed_transaction_set::const_iterator j = wtxid ?
get_iter_from_wtxid(hashb) : mapTx.find(hashb);
770 if (j == mapTx.end())
return false;
771 indexed_transaction_set::const_iterator i = wtxid ?
get_iter_from_wtxid(hasha) : mapTx.find(hasha);
772 if (i == mapTx.end())
return true;
773 uint64_t counta = i->GetCountWithAncestors();
774 uint64_t countb = j->GetCountWithAncestors();
775 if (counta == countb) {
778 return counta < countb;
782 class DepthAndScoreComparator
785 bool operator()(
const CTxMemPool::indexed_transaction_set::const_iterator& a,
const CTxMemPool::indexed_transaction_set::const_iterator& b)
787 uint64_t counta = a->GetCountWithAncestors();
788 uint64_t countb = b->GetCountWithAncestors();
789 if (counta == countb) {
792 return counta < countb;
799 std::vector<indexed_transaction_set::const_iterator> iters;
802 iters.reserve(mapTx.size());
804 for (indexed_transaction_set::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi) {
807 std::sort(iters.begin(), iters.end(), DepthAndScoreComparator());
812 return TxMempoolInfo{it->GetSharedTx(), it->GetTime(), it->GetFee(), it->GetTxSize(), it->GetModifiedFee() - it->GetFee()};
819 std::vector<CTxMemPoolEntryRef>
ret;
820 ret.reserve(mapTx.size());
822 ret.emplace_back(*
it);
832 std::vector<TxMempoolInfo>
ret;
833 ret.reserve(mapTx.size());
834 for (
auto it : iters) {
844 const auto i = mapTx.find(txid);
845 return i == mapTx.end() ? nullptr : &(*i);
851 indexed_transaction_set::const_iterator i = mapTx.find(hash);
852 if (i == mapTx.end())
854 return i->GetSharedTx();
861 if (i == mapTx.end())
870 if (i != mapTx.end() && i->GetSequence() < last_sequence) {
881 CAmount &delta = mapDeltas[hash];
884 if (
it != mapTx.end()) {
888 for (
txiter ancestorIt : ancestors) {
894 setDescendants.erase(
it);
895 for (
txiter descendantIt : setDescendants) {
901 mapDeltas.erase(hash);
902 LogPrintf(
"PrioritiseTransaction: %s (%sin mempool) delta cleared\n", hash.
ToString(),
it == mapTx.end() ?
"not " :
"");
904 LogPrintf(
"PrioritiseTransaction: %s (%sin mempool) fee += %s, new delta=%s\n",
906 it == mapTx.end() ?
"not " :
"",
916 std::map<uint256, CAmount>::const_iterator pos = mapDeltas.find(hash);
917 if (pos == mapDeltas.end())
919 const CAmount &delta = pos->second;
926 mapDeltas.erase(hash);
933 std::vector<delta_info> result;
934 result.reserve(mapDeltas.size());
935 for (
const auto& [txid, delta] : mapDeltas) {
936 const auto iter{mapTx.find(txid)};
937 const bool in_mempool{iter != mapTx.end()};
938 std::optional<CAmount> modified_fee;
939 if (in_mempool) modified_fee = iter->GetModifiedFee();
940 result.emplace_back(
delta_info{in_mempool, delta, modified_fee, txid});
947 const auto it = mapNextTx.find(prevout);
948 return it == mapNextTx.end() ? nullptr :
it->second;
953 auto it = mapTx.find(txid);
954 if (
it != mapTx.end())
return it;
961 for (
const auto& h : hashes) {
963 if (mi)
ret.insert(*mi);
971 std::vector<txiter>
ret;
972 ret.reserve(txids.size());
973 for (
const auto& txid : txids) {
983 for (
unsigned int i = 0; i < tx.
vin.size(); i++)
1004 if (outpoint.
n < ptx->vout.size()) {
1017 for (
unsigned int n = 0; n < tx->vout.size(); ++n) {
1037 if (m_unbroadcast_txids.erase(txid))
1039 LogPrint(
BCLog::MEMPOOL,
"Removed %i from set of unbroadcast txns%s\n", txid.
GetHex(), (unchecked ?
" before confirmation that txn was sent out" :
""));
1054 indexed_transaction_set::index<entry_time>::type::iterator
it = mapTx.get<
entry_time>().begin();
1056 while (
it != mapTx.get<
entry_time>().end() &&
it->GetTime() < time) {
1057 toremove.insert(mapTx.project<0>(
it));
1061 for (
txiter removeit : toremove) {
1065 return stage.size();
1078 if (add && entry->GetMemPoolChildren().insert(*child).second) {
1080 }
else if (!add && entry->GetMemPoolChildren().erase(*child)) {
1089 if (add && entry->GetMemPoolParents().insert(*parent).second) {
1091 }
else if (!add && entry->GetMemPoolParents().erase(*parent)) {
1098 if (!blockSinceLastRollingFeeBump || rollingMinimumFeeRate == 0)
1099 return CFeeRate(llround(rollingMinimumFeeRate));
1102 if (time > lastRollingFeeUpdate + 10) {
1109 rollingMinimumFeeRate = rollingMinimumFeeRate / pow(2.0, (time - lastRollingFeeUpdate) / halflife);
1110 lastRollingFeeUpdate = time;
1113 rollingMinimumFeeRate = 0;
1122 if (rate.
GetFeePerK() > rollingMinimumFeeRate) {
1124 blockSinceLastRollingFeeBump =
false;
1131 unsigned nTxnRemoved = 0;
1134 indexed_transaction_set::index<descendant_score>::type::iterator
it = mapTx.get<
descendant_score>().begin();
1140 CFeeRate removed(
it->GetModFeesWithDescendants(),
it->GetSizeWithDescendants());
1143 maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed);
1147 nTxnRemoved += stage.size();
1149 std::vector<CTransaction> txn;
1150 if (pvNoSpendsRemaining) {
1151 txn.reserve(stage.size());
1152 for (
txiter iter : stage)
1153 txn.push_back(iter->GetTx());
1156 if (pvNoSpendsRemaining) {
1160 pvNoSpendsRemaining->push_back(txin.
prevout);
1166 if (maxFeeRateRemoved >
CFeeRate(0)) {
1173 std::vector<txiter> candidates;
1175 candidates.push_back(entry);
1176 uint64_t maximum = 0;
1177 while (candidates.size()) {
1178 txiter candidate = candidates.back();
1179 candidates.pop_back();
1180 if (!counted.insert(candidate).second)
continue;
1182 if (parents.size() == 0) {
1183 maximum = std::max(maximum, candidate->GetCountWithDescendants());
1186 candidates.push_back(mapTx.iterator_to(i));
1195 auto it = mapTx.find(txid);
1196 ancestors = descendants = 0;
1197 if (
it != mapTx.end()) {
1198 ancestors =
it->GetCountWithAncestors();
1199 if (ancestorsize) *ancestorsize =
it->GetSizeWithAncestors();
1200 if (ancestorfees) *ancestorfees =
it->GetModFeesWithAncestors();
1208 return m_load_tried;
1214 m_load_tried = load_tried;
1220 std::vector<txiter> clustered_txs{
GetIterVec(txids)};
1224 for (
const auto&
it : clustered_txs) {
1228 for (
size_t i{0}; i < clustered_txs.size(); ++i) {
1230 if (clustered_txs.size() > 500)
return {};
1231 const txiter& tx_iter = clustered_txs.at(i);
1232 for (
const auto& entries : {tx_iter->GetMemPoolParentsConst(), tx_iter->GetMemPoolChildrenConst()}) {
1234 const auto entry_it = mapTx.iterator_to(entry);
1236 clustered_txs.push_back(entry_it);
1241 return clustered_txs;
1246 for (
const auto& direct_conflict : direct_conflicts) {
1248 const auto ancestor_count{direct_conflict->GetCountWithAncestors()};
1249 const auto descendant_count{direct_conflict->GetCountWithDescendants()};
1250 const bool has_ancestor{ancestor_count > 1};
1251 const bool has_descendant{descendant_count > 1};
1252 const auto& txid_string{direct_conflict->GetSharedTx()->GetHash().ToString()};
1257 if (ancestor_count > 2) {
1258 return strprintf(
"%s has %u ancestors, max 1 allowed", txid_string, ancestor_count - 1);
1259 }
else if (descendant_count > 2) {
1260 return strprintf(
"%s has %u descendants, max 1 allowed", txid_string, descendant_count - 1);
1261 }
else if (has_ancestor && has_descendant) {
1262 return strprintf(
"%s has both ancestor and descendant, exceeding cluster limit of 2", txid_string);
1267 if (has_descendant) {
1268 const auto& our_child = direct_conflict->GetMemPoolChildrenConst().begin();
1269 if (our_child->get().GetCountWithAncestors() > 2) {
1270 return strprintf(
"%s is not the only parent of child %s",
1271 txid_string, our_child->get().GetSharedTx()->GetHash().ToString());
1273 }
else if (has_ancestor) {
1274 const auto& our_parent = direct_conflict->GetMemPoolParentsConst().begin();
1275 if (our_parent->get().GetCountWithDescendants() > 2) {
1276 return strprintf(
"%s is not the only child of parent %s",
1277 txid_string, our_parent->get().GetSharedTx()->GetHash().ToString());
1281 return std::nullopt;
1286 Assume(replacement_vsize > 0);
1289 if (err_string.has_value()) {
1303 std::vector<FeeFrac> old_chunks;
1310 for (
auto txiter : all_conflicts) {
1312 if (
txiter->GetCountWithDescendants() > 1) {
1318 if (
txiter->GetCountWithAncestors() > 1) {
1321 FeeFrac package{
txiter->GetModFeesWithAncestors(),
static_cast<int32_t
>(
txiter->GetSizeWithAncestors())};
1322 if (individual >> package) {
1326 old_chunks.emplace_back(package);
1329 old_chunks.emplace_back(package - individual);
1330 old_chunks.emplace_back(individual);
1333 old_chunks.emplace_back(individual);
1338 std::sort(old_chunks.begin(), old_chunks.end(), std::greater());
1340 std::vector<FeeFrac> new_chunks;
1350 for (
auto direct_conflict : direct_conflicts) {
1353 if (direct_conflict->GetMemPoolParentsConst().size() > 0) {
1356 if (!all_conflicts.count(mapTx.iterator_to(parent))) {
1364 new_chunks.emplace_back(replacement_fees, int32_t(replacement_vsize));
1367 std::sort(new_chunks.begin(), new_chunks.end(), std::greater());
1368 return std::make_pair(old_chunks, new_chunks);
std::shared_ptr< const CTransaction > CTransactionRef
void UpdateDescendantState(int32_t modifySize, CAmount modifyFee, int64_t modifyCount)
Information about a mempool transaction.
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.
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...
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...
CAmount nModFeesWithDescendants
... and total fees (all including us)
std::string RemovalReasonToString(const MemPoolRemovalReason &r) noexcept
void UpdateModifiedFee(CAmount fee_diff)
CTxMemPool(Options opts, bilingual_str &error)
Create a new CTxMemPool.
#define LogPrint(category,...)
indexed_transaction_set::nth_index< 0 >::type::const_iterator txiter
virtual bool GetCoin(const COutPoint &outpoint, Coin &coin) const
Retrieve the Coin (unspent transaction output) for a given outpoint.
std::vector< TxMempoolInfo > infoAll() const
int32_t GetTxSize() const
bool exists(const GenTxid >xid) const
void UpdateTransactionsFromBlock(const std::vector< uint256 > &vHashesToUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs
UpdateTransactionsFromBlock is called when adding transactions from a disconnected block back to the ...
Options struct containing limit options for a CTxMemPool.
An in-memory indexed chain of blocks.
void CalculateDescendants(txiter it, setEntries &setDescendants) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Populate setDescendants with all in-mempool descendants of hash.
static size_t DynamicUsage(const int8_t &v)
Dynamic memory usage for built-in types is zero.
size_t DynamicMemoryUsage() const
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override
GetCoin, returning whether it exists and is not spent.
util::Result< std::pair< std::vector< FeeFrac >, std::vector< FeeFrac > > > CalculateChunksForRBF(CAmount replacement_fees, int64_t replacement_vsize, const setEntries &direct_conflicts, const setEntries &all_conflicts) EXCLUSIVE_LOCKS_REQUIRED(cs)
Calculate the sorted chunks for the old and new mempool relating to the clusters that would be affect...
ValidationSignals * signals
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
std::vector< CTransactionRef > Package
A package is an ordered list of transactions.
MemPoolRemovalReason
Reason why a transaction was removed from the mempool, this is passed to the notification signal...
void removeConflicts(const CTransaction &tx) EXCLUSIVE_LOCKS_REQUIRED(cs)
void RemoveStaged(setEntries &stage, bool updateDescendants, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
Remove a set of transactions from the mempool.
Removed for conflict with in-block transaction.
bool CompareDepthAndScore(const uint256 &hasha, const uint256 &hashb, bool wtxid=false)
std::set< txiter, CompareIteratorByHash > setEntries
const Children & GetMemPoolChildrenConst() const
std::atomic< unsigned int > nTransactionsUpdated
Used by getblocktemplate to trigger CreateNewBlock() invocation.
void removeRecursive(const CTransaction &tx, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
void SetLoadTried(bool load_tried)
Set whether or not an initial attempt to load the persisted mempool was made (regardless of whether t...
CFeeRate GetMinFee() const
The minimum fee to get into the mempool, which may itself not be enough for larger-sized 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.
CAmount GetModifiedFee() const
#define WITH_FRESH_EPOCH(epoch)
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.
bool isSpent(const COutPoint &outpoint) const
static constexpr ExplicitCopyTag ExplicitCopy
const std::vector< CTxIn > vin
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...
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.
CTxMemPoolEntry stores data about the corresponding transaction, as well as data about all in-mempool...
int64_t nSizeWithAncestors
void UpdateAncestorsOf(bool add, txiter hash, setEntries &setAncestors) EXCLUSIVE_LOCKS_REQUIRED(cs)
Update ancestors of hash to add/remove it as a descendant transaction.
int64_t CAmount
Amount in satoshis (Can be negative)
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...
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.
static const uint32_t MEMPOOL_HEIGHT
Fake height value used in Coin to signify they are only in the memory pool (since 0...
int64_t nSigOpCostWithAncestors
std::set< CTxMemPoolEntryRef, CompareIteratorByHash > Parents
static TxMempoolInfo GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it)
int64_t m_count_with_descendants
number of descendant transactions
Abstract view on the open txout dataset.
size_t DynamicMemoryUsage() const
int Expire(std::chrono::seconds time) EXCLUSIVE_LOCKS_REQUIRED(cs)
Expire all transaction (and their dependencies) in the mempool older than time.
An input of a transaction.
int64_t descendant_count
The maximum allowed number of transactions in a package including the entry and its descendants...
Removed for reorganization.
const CAmount & GetFee() const
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
void removeUnchecked(txiter entry, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
Before calling removeUnchecked for a given transaction, UpdateForRemoveFromMempool must be called on ...
std::string ToString(const FeeEstimateMode &fee_estimate_mode=FeeEstimateMode::BTC_KVB) const
const std::vector< CTxOut > vout
Removed in size limiting.
bool TestLockPointValidity(CChain &active_chain, const LockPoints &lp)
Test whether the LockPoints height and time are still valid on the current chain. ...
std::vector< delta_info > GetPrioritisedTransactions() const EXCLUSIVE_LOCKS_REQUIRED(!cs)
Return a vector of all entries in mapDeltas with their corresponding delta_info.
#define LogPrintLevel(category, level,...)
static const int ROLLING_FEE_HALFLIFE
CAmount nModFeesWithAncestors
std::string ToString() const
constexpr const std::byte * data() const
const CTransaction * GetConflictTx(const COutPoint &prevout) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Get the transaction in the pool that spends the same prevout.
int64_t m_count_with_ancestors
An outpoint - a combination of a transaction hash and an index n into its vout.
void AddTransactionsUpdated(unsigned int n)
void ApplyDelta(const uint256 &hash, CAmount &nFeeDelta) const EXCLUSIVE_LOCKS_REQUIRED(cs)
#define Assume(val)
Assume is the identity function.
int64_t ancestor_size_vbytes
The maximum allowed size in virtual bytes of an entry and its ancestors within a package.
#define TRACE5(context, event, a, b, c, d, e)
uint64_t CalculateDescendantMaximum(txiter entry) const EXCLUSIVE_LOCKS_REQUIRED(cs)
static size_t MallocUsage(size_t alloc)
Compute the total memory used by allocating alloc bytes.
bool GetLoadTried() const
TxMempoolInfo info_for_relay(const GenTxid >xid, uint64_t last_sequence) const
Returns info for a transaction if its entry_sequence < last_sequence.
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...
std::optional< txiter > GetIter(const uint256 &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Returns an iterator to the given hash, if found.
void check(const CCoinsViewCache &active_coins_tip, int64_t spendheight) const EXCLUSIVE_LOCKS_REQUIRED(void cs_main
std::string FormatMoney(const CAmount n)
Money parsing/formatting utilities.
T SaturatingAdd(const T i, const T j) noexcept
const CTxMemPoolEntry * GetEntry(const Txid &txid) const LIFETIMEBOUND EXCLUSIVE_LOCKS_REQUIRED(cs)
uint64_t GetAndIncrementSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs)
Guards this internal counter for external reporting.
std::vector< indexed_transaction_set::const_iterator > GetSortedDepthAndScore() const EXCLUSIVE_LOCKS_REQUIRED(cs)
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...
void MempoolTransactionsRemovedForBlock(const std::vector< RemovedMempoolTransactionInfo > &, unsigned int nBlockHeight)
Data structure storing a fee and size, ordered by increasing fee/size.
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
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...
#define TRACE3(context, event, a, b, c)
void UpdateAncestorState(int32_t modifySize, CAmount modifyFee, int64_t modifyCount, int64_t modifySigOps)
void Reset()
Clear m_temp_added and m_non_base_coins.
int64_t nSizeWithDescendants
... and size
std::map< txiter, setEntries, CompareIteratorByHash > cacheMap
static transaction_identifier FromUint256(const uint256 &id)
int64_t descendant_size_vbytes
The maximum allowed size in virtual bytes of an entry and its descendants within a package...
const CTransaction & GetTx() const
void UpdateEntryForAncestors(txiter it, const setEntries &setAncestors) EXCLUSIVE_LOCKS_REQUIRED(cs)
Set ancestor state for an entry.
TxMempoolInfo info(const GenTxid >xid) const
txiter get_iter_from_wtxid(const uint256 &wtxid) const EXCLUSIVE_LOCKS_REQUIRED(cs)
void UpdateChild(txiter entry, txiter child, bool add) EXCLUSIVE_LOCKS_REQUIRED(cs)
void ClearPrioritisation(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs)
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.
std::string GetHex() const
std::optional< std::string > CheckConflictTopology(const setEntries &direct_conflicts)
std::set< CTxMemPoolEntryRef, CompareIteratorByHash > Children
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
#define AssertLockNotHeld(cs)
unsigned int GetTransactionsUpdated() const
bilingual_str ErrorString(const Result< T > &result)
static size_t IncrementalDynamicUsage(const std::set< X, Y > &s)
void PackageAddTransaction(const CTransactionRef &tx)
Add the coins created by this transaction.
static CTxMemPool::Options && Flatten(CTxMemPool::Options &&opts, bilingual_str &error)
Clamp option values and populate the error if options are not valid.
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.
CTransactionRef get(const uint256 &hash) const
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...
void RemoveUnbroadcastTx(const uint256 &txid, const bool unchecked=false)
Removes a transaction from the unbroadcast set.
void trackPackageRemoved(const CFeeRate &rate) EXCLUSIVE_LOCKS_REQUIRED(cs)
CCoinsViewMemPool(CCoinsView *baseIn, const CTxMemPool &mempoolIn)
static constexpr MemPoolLimits NoLimits()
Options struct containing options for constructing a CTxMemPool.
The basic transaction that is broadcasted on the network and contained in blocks. ...
CCoinsView backed by another CCoinsView.
int64_t ancestor_count
The maximum allowed number of transactions in a package including the entry and its ancestors...
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Sort by feerate of entry (fee/size) in descending order This is only used for transaction relay...
void UpdateParent(txiter entry, txiter parent, bool add) EXCLUSIVE_LOCKS_REQUIRED(cs)
const CTxMemPool & mempool
int64_t GetTime()
DEPRECATED, see GetTime.
void UpdateChildrenForRemoval(txiter entry) EXCLUSIVE_LOCKS_REQUIRED(cs)
Sever link between specified transaction and direct children.
const Parents & GetMemPoolParentsConst() const
CBlockIndex * maxInputBlock
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
bilingual_str _(ConstevalStringLiteral str)
Translation function.
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...
void removeForBlock(const std::vector< CTransactionRef > &vtx, unsigned int nBlockHeight) EXCLUSIVE_LOCKS_REQUIRED(cs)
Called when a block is connected.
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. ...
void PrioritiseTransaction(const uint256 &hash, const CAmount &nFeeDelta)
Affect CreateNewBlock prioritisation of transactions.
A generic txid reference (txid or wtxid).
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
std::unordered_map< COutPoint, Coin, SaltedOutpointHasher > m_temp_added
Coins made available by transactions being validated.
static GenTxid Txid(const uint256 &hash)
std::vector< CTxMemPoolEntryRef > entryAll() const EXCLUSIVE_LOCKS_REQUIRED(cs)
void UpdateForRemoveFromMempool(const setEntries &entriesToRemove, bool updateDescendants) EXCLUSIVE_LOCKS_REQUIRED(cs)
For each transaction being removed, update ancestors and any direct children.
const uint256 & GetHash() const LIFETIMEBOUND
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it...
#define Assert(val)
Identity function.
const Txid & GetHash() const LIFETIMEBOUND
CFeeRate incremental_relay_feerate
void TransactionRemovedFromMempool(const CTransactionRef &, MemPoolRemovalReason, uint64_t mempool_sequence)