58 const std::set<Txid>& setExclude, std::set<Txid>& descendants_to_remove)
61 stageEntries = updateIt->GetMemPoolChildrenConst();
63 while (!stageEntries.empty()) {
65 descendants.insert(descendant);
66 stageEntries.erase(descendant);
69 cacheMap::iterator cacheIt = cachedDescendants.find(mapTx.iterator_to(childEntry));
70 if (cacheIt != cachedDescendants.end()) {
73 for (
txiter cacheEntry : cacheIt->second) {
74 descendants.insert(*cacheEntry);
76 }
else if (!descendants.count(childEntry)) {
78 stageEntries.insert(childEntry);
84 int32_t modifySize = 0;
86 int64_t modifyCount = 0;
88 if (!setExclude.count(descendant.GetTx().GetHash())) {
89 modifySize += descendant.GetTxSize();
90 modifyFee += descendant.GetModifiedFee();
92 cachedDescendants[updateIt].insert(mapTx.iterator_to(descendant));
95 e.UpdateAncestorState(updateIt->GetTxSize(), updateIt->GetModifiedFee(), 1, updateIt->GetSigOpCost());
101 descendants_to_remove.insert(descendant.GetTx().GetHash());
114 cacheMap mapMemPoolDescendantsToUpdate;
118 std::set<Txid> setAlreadyIncluded(vHashesToUpdate.begin(), vHashesToUpdate.end());
120 std::set<Txid> descendants_to_remove;
127 for (
const Txid& hash : vHashesToUpdate | std::views::reverse) {
130 if (
it == mapTx.end()) {
133 auto iter = mapNextTx.lower_bound(
COutPoint(hash, 0));
139 for (; iter != mapNextTx.end() && iter->first->hash == hash; ++iter) {
140 const Txid &childHash = iter->second->GetHash();
141 txiter childIter = mapTx.find(childHash);
142 assert(childIter != mapTx.end());
145 if (!
visited(childIter) && !setAlreadyIncluded.count(childHash)) {
154 for (
const auto& txid : descendants_to_remove) {
167 const Limits& limits)
const
169 int64_t totalSizeWithAncestors = entry_size;
172 while (!staged_ancestors.empty()) {
174 txiter stageit = mapTx.iterator_to(stage);
176 ancestors.insert(stageit);
177 staged_ancestors.erase(stage);
178 totalSizeWithAncestors += stageit->
GetTxSize();
182 }
else if (stageit->GetCountWithDescendants() + entry_count >
static_cast<uint64_t
>(limits.
descendant_count)) {
190 txiter parent_it = mapTx.iterator_to(parent);
193 if (ancestors.count(parent_it) == 0) {
194 staged_ancestors.insert(parent);
196 if (staged_ancestors.size() + ancestors.size() + entry_count >
static_cast<uint64_t
>(limits.
ancestor_count)) {
206 const int64_t total_vsize)
const
208 size_t pack_count = package.size();
222 for (
const auto& tx : package) {
223 for (
const auto& input : tx->vin) {
224 std::optional<txiter> piter =
GetIter(input.prevout.hash);
226 staged_ancestors.insert(**piter);
246 bool fSearchForParents )
const
251 if (fSearchForParents) {
255 for (
unsigned int i = 0; i < tx.
vin.size(); i++) {
256 std::optional<txiter> piter =
GetIter(tx.
vin[i].prevout.hash);
258 staged_ancestors.insert(**piter);
259 if (staged_ancestors.size() + 1 >
static_cast<uint64_t
>(limits.
ancestor_count)) {
267 txiter it = mapTx.iterator_to(entry);
268 staged_ancestors =
it->GetMemPoolParentsConst();
276 std::string_view calling_fn_name,
279 bool fSearchForParents )
const
296 const int32_t updateCount = (add ? 1 : -1);
297 const int32_t updateSize{updateCount *
it->GetTxSize()};
298 const CAmount updateFee = updateCount *
it->GetModifiedFee();
299 for (
txiter ancestorIt : setAncestors) {
306 int64_t updateCount = setAncestors.size();
307 int64_t updateSize = 0;
309 int64_t updateSigOpsCost = 0;
310 for (
txiter ancestorIt : setAncestors) {
311 updateSize += ancestorIt->GetTxSize();
312 updateFee += ancestorIt->GetModifiedFee();
313 updateSigOpsCost += ancestorIt->GetSigOpCost();
330 if (updateDescendants) {
337 for (
txiter removeIt : entriesToRemove) {
340 setDescendants.erase(removeIt);
341 int32_t modifySize = -removeIt->GetTxSize();
342 CAmount modifyFee = -removeIt->GetModifiedFee();
343 int modifySigOps = -removeIt->GetSigOpCost();
344 for (
txiter dit : setDescendants) {
349 for (
txiter removeIt : entriesToRemove) {
378 for (
txiter removeIt : entriesToRemove) {
406 opts.
check_ratio = std::clamp<int>(opts.check_ratio, 0, 1'000'000);
407 int64_t descendant_limit_bytes = opts.limits.descendant_size_vbytes * 40;
408 if (opts.max_size_bytes < 0 || opts.max_size_bytes < descendant_limit_bytes) {
409 error =
strprintf(
_(
"-maxmempool must be at least %d MB"), std::ceil(descendant_limit_bytes / 1'000'000.0));
411 return std::move(opts);
422 return mapNextTx.count(outpoint);
440 for (
size_t i=0; i<changeset->
m_entry_vec.size(); ++i) {
442 std::optional<CTxMemPool::setEntries> ancestors;
456 auto node_handle = changeset->
m_to_add.extract(tx_entry);
457 auto result = mapTx.insert(std::move(node_handle));
463 if (ancestors.has_value()) {
487 std::set<Txid> setParentTransactions;
488 for (
unsigned int i = 0; i < tx.
vin.size(); i++) {
489 mapNextTx.insert(std::make_pair(&tx.
vin[i].prevout, &tx));
490 setParentTransactions.insert(tx.
vin[i].prevout.hash);
500 for (
const auto& pit :
GetIterSet(setParentTransactions)) {
508 m_total_fee += entry.
GetFee();
510 txns_randomized.emplace_back(newit->GetSharedTx());
511 newit->idx_randomized = txns_randomized.size() - 1;
534 it->GetTx().GetHash().data(),
538 std::chrono::duration_cast<std::chrono::duration<std::uint64_t>>(
it->GetTime()).count()
541 for (
const CTxIn& txin :
it->GetTx().vin)
542 mapNextTx.erase(txin.prevout);
546 if (txns_randomized.size() > 1) {
548 Assert(
GetEntry(txns_randomized.back()->GetHash()))->idx_randomized =
it->idx_randomized;
550 txns_randomized[
it->idx_randomized] = std::move(txns_randomized.back());
551 txns_randomized.pop_back();
552 if (txns_randomized.size() * 2 < txns_randomized.capacity())
553 txns_randomized.shrink_to_fit();
555 txns_randomized.clear();
557 totalTxSize -=
it->GetTxSize();
558 m_total_fee -=
it->GetFee();
559 cachedInnerUsage -=
it->DynamicMemoryUsage();
574 if (setDescendants.count(entryit) == 0) {
575 stage.insert(entryit);
580 while (!stage.empty()) {
582 setDescendants.insert(
it);
587 txiter childiter = mapTx.iterator_to(child);
588 if (!setDescendants.count(childiter)) {
589 stage.insert(childiter);
599 Assume(!m_have_changeset);
602 if (origit != mapTx.end()) {
603 txToRemove.insert(origit);
609 for (
unsigned int i = 0; i < origTx.
vout.size(); i++) {
611 if (
it == mapNextTx.end())
613 txiter nextit = mapTx.find(
it->second->GetHash());
614 assert(nextit != mapTx.end());
615 txToRemove.insert(nextit);
631 Assume(!m_have_changeset);
634 for (indexed_transaction_set::const_iterator
it = mapTx.begin();
it != mapTx.end();
it++) {
635 if (check_final_and_mature(
it)) txToRemove.insert(
it);
642 for (indexed_transaction_set::const_iterator
it = mapTx.begin();
it != mapTx.end();
it++) {
653 if (
it != mapNextTx.end()) {
668 Assume(!m_have_changeset);
669 std::vector<RemovedMempoolTransactionInfo> txs_removed_for_block;
670 if (mapTx.size() || mapNextTx.size() || mapDeltas.size()) {
671 txs_removed_for_block.reserve(vtx.size());
672 for (
const auto& tx : vtx) {
673 txiter it = mapTx.find(tx->GetHash());
674 if (
it != mapTx.end()) {
677 txs_removed_for_block.emplace_back(*
it);
687 lastRollingFeeUpdate =
GetTime();
688 blockSinceLastRollingFeeBump =
true;
691void CTxMemPool::check(
const CCoinsViewCache& active_coins_tip, int64_t spendheight)
const
699 LogDebug(
BCLog::MEMPOOL,
"Checking mempool with %u transactions and %u inputs\n", (
unsigned int)mapTx.size(), (
unsigned int)mapNextTx.size());
701 uint64_t checkTotal = 0;
703 uint64_t innerUsage = 0;
704 uint64_t prev_ancestor_count{0};
709 checkTotal +=
it->GetTxSize();
710 check_total_fee +=
it->GetFee();
711 innerUsage +=
it->DynamicMemoryUsage();
717 indexed_transaction_set::const_iterator it2 = mapTx.find(txin.
prevout.
hash);
718 if (it2 != mapTx.end()) {
721 setParentCheck.insert(*it2);
728 auto it3 = mapNextTx.find(txin.
prevout);
729 assert(it3 != mapNextTx.end());
731 assert(it3->second == &tx);
736 assert(setParentCheck.size() ==
it->GetMemPoolParentsConst().size());
737 assert(std::equal(setParentCheck.begin(), setParentCheck.end(),
it->GetMemPoolParentsConst().begin(), comp));
740 uint64_t nCountCheck = ancestors.size() + 1;
741 int32_t nSizeCheck =
it->GetTxSize();
742 CAmount nFeesCheck =
it->GetModifiedFee();
743 int64_t nSigOpCheck =
it->GetSigOpCost();
745 for (
txiter ancestorIt : ancestors) {
746 nSizeCheck += ancestorIt->GetTxSize();
747 nFeesCheck += ancestorIt->GetModifiedFee();
748 nSigOpCheck += ancestorIt->GetSigOpCost();
751 assert(
it->GetCountWithAncestors() == nCountCheck);
752 assert(
it->GetSizeWithAncestors() == nSizeCheck);
753 assert(
it->GetSigOpCostWithAncestors() == nSigOpCheck);
754 assert(
it->GetModFeesWithAncestors() == nFeesCheck);
756 assert(prev_ancestor_count <= it->GetCountWithAncestors());
757 prev_ancestor_count =
it->GetCountWithAncestors();
761 auto iter = mapNextTx.lower_bound(
COutPoint(
it->GetTx().GetHash(), 0));
762 int32_t child_sizes{0};
763 for (; iter != mapNextTx.end() && iter->first->hash ==
it->GetTx().GetHash(); ++iter) {
764 txiter childit = mapTx.find(iter->second->GetHash());
765 assert(childit != mapTx.end());
766 if (setChildrenCheck.insert(*childit).second) {
767 child_sizes += childit->GetTxSize();
770 assert(setChildrenCheck.size() ==
it->GetMemPoolChildrenConst().size());
771 assert(std::equal(setChildrenCheck.begin(), setChildrenCheck.end(),
it->GetMemPoolChildrenConst().begin(), comp));
774 assert(
it->GetSizeWithDescendants() >= child_sizes +
it->GetTxSize());
780 for (
const auto& input: tx.
vin) mempoolDuplicate.SpendCoin(input.prevout);
781 AddCoins(mempoolDuplicate, tx, std::numeric_limits<int>::max());
783 for (
const auto& [
_, next_tx] : mapNextTx) {
784 auto it = mapTx.find(next_tx->GetHash());
790 assert(totalTxSize == checkTotal);
791 assert(m_total_fee == check_total_fee);
792 assert(innerUsage == cachedInnerUsage);
804 if (!j.has_value())
return false;
806 if (!i.has_value())
return true;
807 uint64_t counta = i.value()->GetCountWithAncestors();
808 uint64_t countb = j.value()->GetCountWithAncestors();
809 if (counta == countb) {
812 return counta < countb;
816class DepthAndScoreComparator
819 bool operator()(
const CTxMemPool::indexed_transaction_set::const_iterator& a,
const CTxMemPool::indexed_transaction_set::const_iterator& b)
821 uint64_t counta = a->GetCountWithAncestors();
822 uint64_t countb = b->GetCountWithAncestors();
823 if (counta == countb) {
826 return counta < countb;
833 std::vector<indexed_transaction_set::const_iterator> iters;
836 iters.reserve(mapTx.size());
838 for (indexed_transaction_set::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi) {
841 std::sort(iters.begin(), iters.end(), DepthAndScoreComparator());
849 std::vector<CTxMemPoolEntryRef>
ret;
850 ret.reserve(mapTx.size());
852 ret.emplace_back(*
it);
862 std::vector<TxMempoolInfo>
ret;
863 ret.reserve(mapTx.size());
864 for (
auto it : iters) {
874 const auto i = mapTx.find(txid);
875 return i == mapTx.end() ? nullptr : &(*i);
881 indexed_transaction_set::const_iterator i = mapTx.find(hash);
882 if (i == mapTx.end())
884 return i->GetSharedTx();
891 CAmount &delta = mapDeltas[hash];
894 if (
it != mapTx.end()) {
898 for (
txiter ancestorIt : ancestors) {
904 setDescendants.erase(
it);
905 for (
txiter descendantIt : setDescendants) {
911 mapDeltas.erase(hash);
912 LogPrintf(
"PrioritiseTransaction: %s (%sin mempool) delta cleared\n", hash.
ToString(),
it == mapTx.end() ?
"not " :
"");
914 LogPrintf(
"PrioritiseTransaction: %s (%sin mempool) fee += %s, new delta=%s\n",
916 it == mapTx.end() ?
"not " :
"",
926 std::map<Txid, CAmount>::const_iterator pos = mapDeltas.find(hash);
927 if (pos == mapDeltas.end())
929 const CAmount &delta = pos->second;
936 mapDeltas.erase(hash);
943 std::vector<delta_info> result;
944 result.reserve(mapDeltas.size());
945 for (
const auto& [txid, delta] : mapDeltas) {
946 const auto iter{mapTx.find(txid)};
947 const bool in_mempool{iter != mapTx.end()};
948 std::optional<CAmount> modified_fee;
949 if (in_mempool) modified_fee = iter->GetModifiedFee();
950 result.emplace_back(
delta_info{in_mempool, delta, modified_fee, txid});
957 const auto it = mapNextTx.find(prevout);
958 return it == mapNextTx.end() ? nullptr :
it->second;
964 auto it = mapTx.find(txid);
965 return it != mapTx.end() ? std::make_optional(
it) : std::nullopt;
972 return it != mapTx.end() ? std::make_optional(
it) : std::nullopt;
978 for (
const auto& h : hashes) {
980 if (mi)
ret.insert(*mi);
988 std::vector<txiter>
ret;
989 ret.reserve(txids.size());
990 for (
const auto& txid : txids) {
1000 for (
unsigned int i = 0; i < tx.
vin.size(); i++)
1021 if (outpoint.
n < ptx->vout.size()) {
1026 return std::nullopt;
1033 for (
unsigned int n = 0; n < tx->vout.size(); ++n) {
1053 if (m_unbroadcast_txids.erase(txid))
1055 LogDebug(
BCLog::MEMPOOL,
"Removed %i from set of unbroadcast txns%s\n", txid.
GetHex(), (unchecked ?
" before confirmation that txn was sent out" :
""));
1070 Assume(!m_have_changeset);
1071 indexed_transaction_set::index<entry_time>::type::iterator
it = mapTx.get<
entry_time>().begin();
1073 while (
it != mapTx.get<
entry_time>().end() &&
it->GetTime() < time) {
1074 toremove.insert(mapTx.project<0>(
it));
1078 for (
txiter removeit : toremove) {
1082 return stage.size();
1089 if (add && entry->GetMemPoolChildren().insert(*child).second) {
1091 }
else if (!add && entry->GetMemPoolChildren().erase(*child)) {
1100 if (add && entry->GetMemPoolParents().insert(*parent).second) {
1102 }
else if (!add && entry->GetMemPoolParents().erase(*parent)) {
1109 if (!blockSinceLastRollingFeeBump || rollingMinimumFeeRate == 0)
1110 return CFeeRate(llround(rollingMinimumFeeRate));
1113 if (time > lastRollingFeeUpdate + 10) {
1120 rollingMinimumFeeRate = rollingMinimumFeeRate / pow(2.0, (time - lastRollingFeeUpdate) / halflife);
1121 lastRollingFeeUpdate = time;
1124 rollingMinimumFeeRate = 0;
1133 if (rate.
GetFeePerK() > rollingMinimumFeeRate) {
1135 blockSinceLastRollingFeeBump =
false;
1141 Assume(!m_have_changeset);
1143 unsigned nTxnRemoved = 0;
1146 indexed_transaction_set::index<descendant_score>::type::iterator
it = mapTx.get<
descendant_score>().begin();
1152 CFeeRate removed(
it->GetModFeesWithDescendants(),
it->GetSizeWithDescendants());
1155 maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed);
1159 nTxnRemoved += stage.size();
1161 std::vector<CTransaction> txn;
1162 if (pvNoSpendsRemaining) {
1163 txn.reserve(stage.size());
1164 for (
txiter iter : stage)
1165 txn.push_back(iter->GetTx());
1168 if (pvNoSpendsRemaining) {
1172 pvNoSpendsRemaining->push_back(txin.
prevout);
1178 if (maxFeeRateRemoved >
CFeeRate(0)) {
1185 std::vector<txiter> candidates;
1187 candidates.push_back(entry);
1188 uint64_t maximum = 0;
1189 while (candidates.size()) {
1190 txiter candidate = candidates.back();
1191 candidates.pop_back();
1192 if (!counted.insert(candidate).second)
continue;
1194 if (parents.size() == 0) {
1195 maximum = std::max(maximum, candidate->GetCountWithDescendants());
1198 candidates.push_back(mapTx.iterator_to(i));
1207 auto it = mapTx.find(txid);
1208 ancestors = descendants = 0;
1209 if (
it != mapTx.end()) {
1210 ancestors =
it->GetCountWithAncestors();
1211 if (ancestorsize) *ancestorsize =
it->GetSizeWithAncestors();
1212 if (ancestorfees) *ancestorfees =
it->GetModFeesWithAncestors();
1220 return m_load_tried;
1226 m_load_tried = load_tried;
1232 std::vector<txiter> clustered_txs{
GetIterVec(txids)};
1236 for (
const auto&
it : clustered_txs) {
1240 for (
size_t i{0}; i < clustered_txs.size(); ++i) {
1242 if (clustered_txs.size() > 500)
return {};
1243 const txiter& tx_iter = clustered_txs.at(i);
1244 for (
const auto& entries : {tx_iter->GetMemPoolParentsConst(), tx_iter->GetMemPoolChildrenConst()}) {
1246 const auto entry_it = mapTx.iterator_to(entry);
1248 clustered_txs.push_back(entry_it);
1253 return clustered_txs;
1258 for (
const auto& direct_conflict : direct_conflicts) {
1260 const auto ancestor_count{direct_conflict->GetCountWithAncestors()};
1261 const auto descendant_count{direct_conflict->GetCountWithDescendants()};
1262 const bool has_ancestor{ancestor_count > 1};
1263 const bool has_descendant{descendant_count > 1};
1264 const auto& txid_string{direct_conflict->GetSharedTx()->GetHash().ToString()};
1269 if (ancestor_count > 2) {
1270 return strprintf(
"%s has %u ancestors, max 1 allowed", txid_string, ancestor_count - 1);
1271 }
else if (descendant_count > 2) {
1272 return strprintf(
"%s has %u descendants, max 1 allowed", txid_string, descendant_count - 1);
1273 }
else if (has_ancestor && has_descendant) {
1274 return strprintf(
"%s has both ancestor and descendant, exceeding cluster limit of 2", txid_string);
1279 if (has_descendant) {
1280 const auto& our_child = direct_conflict->GetMemPoolChildrenConst().begin();
1281 if (our_child->get().GetCountWithAncestors() > 2) {
1282 return strprintf(
"%s is not the only parent of child %s",
1283 txid_string, our_child->get().GetSharedTx()->GetHash().ToString());
1285 }
else if (has_ancestor) {
1286 const auto& our_parent = direct_conflict->GetMemPoolParentsConst().begin();
1287 if (our_parent->get().GetCountWithDescendants() > 2) {
1288 return strprintf(
"%s is not the only child of parent %s",
1289 txid_string, our_parent->get().GetSharedTx()->GetHash().ToString());
1293 return std::nullopt;
1299 FeeFrac replacement_feerate{0, 0};
1301 replacement_feerate += {
it->GetModifiedFee(),
it->GetTxSize()};
1305 if (err_string.has_value()) {
1319 std::vector<FeeFrac> old_chunks;
1328 if (
txiter->GetCountWithDescendants() > 1) {
1334 if (
txiter->GetCountWithAncestors() > 1) {
1337 FeeFrac package{
txiter->GetModFeesWithAncestors(),
static_cast<int32_t
>(
txiter->GetSizeWithAncestors())};
1338 if (individual >> package) {
1342 old_chunks.emplace_back(package);
1345 old_chunks.emplace_back(package - individual);
1346 old_chunks.emplace_back(individual);
1349 old_chunks.emplace_back(individual);
1354 std::sort(old_chunks.begin(), old_chunks.end(), std::greater());
1356 std::vector<FeeFrac> new_chunks;
1369 if (direct_conflict->GetMemPoolParentsConst().size() > 0) {
1380 new_chunks.emplace_back(replacement_feerate);
1383 std::sort(new_chunks.begin(), new_chunks.end(), std::greater());
1384 return std::make_pair(old_chunks, new_chunks);
1390 Assume(m_to_add.find(tx->GetHash()) == m_to_add.end());
1391 auto newit = m_to_add.emplace(tx,
fee, time, entry_height, entry_sequence, spends_coinbase, sigops_cost,
lp).first;
1393 m_pool->ApplyDelta(tx->GetHash(), delta);
1396 m_entry_vec.push_back(newit);
1403 m_pool->Apply(
this);
1405 m_to_remove.clear();
1406 m_entry_vec.clear();
1407 m_ancestors.clear();
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 std::optional< Coin > GetCoin(const COutPoint &outpoint) const
Retrieve the Coin (unspent transaction output) for a given outpoint.
std::optional< Coin > GetCoin(const COutPoint &outpoint) 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 virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac.
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 std::vector< CTxOut > vout
const Txid & GetHash() const LIFETIMEBOUND
const std::vector< CTxIn > vin
An input of a transaction.
CTxMemPool::setEntries m_to_remove
void Apply() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
util::Result< CTxMemPool::setEntries > CalculateMemPoolAncestors(TxHandle tx, const Limits &limits)
TxHandle StageAddition(const CTransactionRef &tx, const CAmount fee, int64_t time, unsigned int entry_height, uint64_t entry_sequence, bool spends_coinbase, int64_t sigops_cost, LockPoints lp)
util::Result< std::pair< std::vector< FeeFrac >, std::vector< FeeFrac > > > CalculateChunksForRBF()
Calculate the sorted chunks for the old and new mempool relating to the clusters that would be affect...
CTxMemPool::txiter TxHandle
CTxMemPool::indexed_transaction_set m_to_add
std::vector< CTxMemPool::txiter > m_entry_vec
CTxMemPoolEntry stores data about the corresponding transaction, as well as data about all in-mempool...
int64_t nSigOpCostWithAncestors
int64_t m_count_with_descendants
number of descendant transactions
void UpdateAncestorState(int32_t modifySize, CAmount modifyFee, int64_t modifyCount, int64_t modifySigOps)
const CTransaction & GetTx() const
CAmount nModFeesWithAncestors
const Children & GetMemPoolChildrenConst() const
const Parents & GetMemPoolParentsConst() const
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
const CAmount & GetFee() const
void UpdateDescendantState(int32_t modifySize, CAmount modifyFee, int64_t modifyCount)
CAmount GetModifiedFee() const
int64_t nSizeWithAncestors
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 Apply(CTxMemPool::ChangeSet *changeset) EXCLUSIVE_LOCKS_REQUIRED(cs)
void PrioritiseTransaction(const Txid &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.
static TxMempoolInfo GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it)
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.
void ClearPrioritisation(const Txid &hash) EXCLUSIVE_LOCKS_REQUIRED(cs)
void UpdateEntryForAncestors(txiter it, const setEntries &setAncestors) EXCLUSIVE_LOCKS_REQUIRED(cs)
Set ancestor state for an entry.
std::optional< txiter > GetIter(const Txid &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Returns an iterator to the given hash, if found.
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 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 check(const CCoinsViewCache &active_coins_tip, int64_t spendheight) const EXCLUSIVE_LOCKS_REQUIRED(void removeRecursive(const CTransaction &tx, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
If sanity-checking is turned on, check makes sure the pool is consistent (does not contain two transa...
void UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendants, const std::set< Txid > &setExclude, std::set< Txid > &descendants_to_remove) EXCLUSIVE_LOCKS_REQUIRED(cs)
UpdateForDescendants is used by UpdateTransactionsFromBlock to update the descendants for a single tr...
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< Txid > &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.
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 Txid &hash) const
size_t DynamicMemoryUsage() const
std::vector< TxMempoolInfo > infoAll() const
CTxMemPool(Options opts, bilingual_str &error)
Create a new CTxMemPool.
void UpdateParent(txiter entry, txiter parent, bool add) EXCLUSIVE_LOCKS_REQUIRED(cs)
void addNewTransaction(CTxMemPool::txiter it) 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 ...
void RemoveUnbroadcastTx(const Txid &txid, const bool unchecked=false)
Removes a transaction from the unbroadcast set.
int Expire(std::chrono::seconds time) EXCLUSIVE_LOCKS_REQUIRED(cs)
Expire all transaction (and their dependencies) in the mempool older than time.
bool CompareDepthAndScore(const Wtxid &hasha, const Wtxid &hashb) const
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...
bool exists(const Txid &txid) const
std::vector< txiter > GetIterVec(const std::vector< Txid > &txids) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Translate a list of hashes into a list of mempool iterators to avoid repeated lookups.
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 ApplyDelta(const Txid &hash, CAmount &nFeeDelta) 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)
std::vector< delta_info > GetPrioritisedTransactions() const EXCLUSIVE_LOCKS_REQUIRED(!cs)
Return a vector of all entries in mapDeltas with their corresponding delta_info.
std::vector< txiter > GatherClusters(const std::vector< Txid > &txids) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Collect the entire cluster of connected transactions for each transaction in txids.
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)
std::map< txiter, setEntries, CompareIteratorByHash > cacheMap
void GetTransactionAncestry(const Txid &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.
const CTransaction * GetConflictTx(const COutPoint &prevout) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Get the transaction in the pool that spends the same prevout.
void CalculateDescendants(txiter it, setEntries &setDescendants) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Populate setDescendants with all in-mempool descendants of hash.
std::optional< std::string > CheckConflictTopology(const setEntries &direct_conflicts)
void SetLoadTried(bool load_tried)
Set whether or not an initial attempt to load the persisted mempool was made (regardless of whether t...
void UpdateForRemoveFromMempool(const setEntries &entriesToRemove, bool updateDescendants) EXCLUSIVE_LOCKS_REQUIRED(cs)
For each transaction being removed, update ancestors and any direct children.
std::vector< CTxMemPoolEntryRef > entryAll() const EXCLUSIVE_LOCKS_REQUIRED(cs)
uint64_t CalculateDescendantMaximum(txiter entry) const EXCLUSIVE_LOCKS_REQUIRED(cs)
bool isSpent(const COutPoint &outpoint) const
const CTxMemPoolEntry * GetEntry(const Txid &txid) const LIFETIMEBOUND EXCLUSIVE_LOCKS_REQUIRED(cs)
unsigned int GetTransactionsUpdated() const
Sort by feerate of entry (fee/size) in descending order This is only used for transaction relay,...
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
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 LogDebug(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.
@ REPLACED
Removed for replacement.
@ 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)
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
Data structure storing a fee and size, ordered by increasing fee/size.
CBlockIndex * maxInputBlock
Options struct containing limit options for a CTxMemPool.
static constexpr MemPoolLimits NoLimits()
int64_t descendant_count
The maximum allowed number of transactions in a package including the entry and its descendants.
int64_t descendant_size_vbytes
The maximum allowed size in virtual bytes of an entry and its descendants within a package.
int64_t ancestor_count
The maximum allowed number of transactions in a package including the entry and its ancestors.
int64_t ancestor_size_vbytes
The maximum allowed size in virtual bytes of an entry and its ancestors within a package.
Options struct containing options for constructing a CTxMemPool.
ValidationSignals * signals
CFeeRate incremental_relay_feerate
#define AssertLockNotHeld(cs)
#define TRACEPOINT(context,...)
consteval auto _(util::TranslatedLiteral str)
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
static CTxMemPool::Options && Flatten(CTxMemPool::Options &&opts, bilingual_str &error)
Clamp option values and populate the error if options are not valid.
TRACEPOINT_SEMAPHORE(mempool, added)
bool TestLockPointValidity(CChain &active_chain, const LockPoints &lp)
Test whether the LockPoints height and time are still valid on the current chain.
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 GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.