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();
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 txns_randomized[
it->idx_randomized] = std::move(txns_randomized.back());
549 txns_randomized[
it->idx_randomized].second->idx_randomized =
it->idx_randomized;
550 txns_randomized.pop_back();
551 if (txns_randomized.size() * 2 < txns_randomized.capacity()) {
552 txns_randomized.shrink_to_fit();
555 txns_randomized.clear();
558 totalTxSize -=
it->GetTxSize();
559 m_total_fee -=
it->GetFee();
560 cachedInnerUsage -=
it->DynamicMemoryUsage();
575 if (setDescendants.count(entryit) == 0) {
576 stage.insert(entryit);
581 while (!stage.empty()) {
583 setDescendants.insert(
it);
588 txiter childiter = mapTx.iterator_to(child);
589 if (!setDescendants.count(childiter)) {
590 stage.insert(childiter);
600 Assume(!m_have_changeset);
603 if (origit != mapTx.end()) {
604 txToRemove.insert(origit);
610 for (
unsigned int i = 0; i < origTx.
vout.size(); i++) {
612 if (
it == mapNextTx.end())
614 txiter nextit = mapTx.find(
it->second->GetHash());
615 assert(nextit != mapTx.end());
616 txToRemove.insert(nextit);
632 Assume(!m_have_changeset);
635 for (indexed_transaction_set::const_iterator
it = mapTx.begin();
it != mapTx.end();
it++) {
636 if (check_final_and_mature(
it)) txToRemove.insert(
it);
643 for (indexed_transaction_set::const_iterator
it = mapTx.begin();
it != mapTx.end();
it++) {
654 if (
it != mapNextTx.end()) {
669 Assume(!m_have_changeset);
670 std::vector<RemovedMempoolTransactionInfo> txs_removed_for_block;
671 if (mapTx.size() || mapNextTx.size() || mapDeltas.size()) {
672 txs_removed_for_block.reserve(vtx.size());
673 for (
const auto& tx : vtx) {
674 txiter it = mapTx.find(tx->GetHash());
675 if (
it != mapTx.end()) {
678 txs_removed_for_block.emplace_back(*
it);
688 lastRollingFeeUpdate =
GetTime();
689 blockSinceLastRollingFeeBump =
true;
692void CTxMemPool::check(
const CCoinsViewCache& active_coins_tip, int64_t spendheight)
const
700 LogDebug(
BCLog::MEMPOOL,
"Checking mempool with %u transactions and %u inputs\n", (
unsigned int)mapTx.size(), (
unsigned int)mapNextTx.size());
702 uint64_t checkTotal = 0;
704 uint64_t innerUsage = 0;
705 uint64_t prev_ancestor_count{0};
710 checkTotal +=
it->GetTxSize();
711 check_total_fee +=
it->GetFee();
712 innerUsage +=
it->DynamicMemoryUsage();
718 indexed_transaction_set::const_iterator it2 = mapTx.find(txin.
prevout.
hash);
719 if (it2 != mapTx.end()) {
722 setParentCheck.insert(*it2);
729 auto it3 = mapNextTx.find(txin.
prevout);
730 assert(it3 != mapNextTx.end());
732 assert(it3->second == &tx);
737 assert(setParentCheck.size() ==
it->GetMemPoolParentsConst().size());
738 assert(std::equal(setParentCheck.begin(), setParentCheck.end(),
it->GetMemPoolParentsConst().begin(), comp));
741 uint64_t nCountCheck = ancestors.size() + 1;
742 int32_t nSizeCheck =
it->GetTxSize();
743 CAmount nFeesCheck =
it->GetModifiedFee();
744 int64_t nSigOpCheck =
it->GetSigOpCost();
746 for (
txiter ancestorIt : ancestors) {
747 nSizeCheck += ancestorIt->GetTxSize();
748 nFeesCheck += ancestorIt->GetModifiedFee();
749 nSigOpCheck += ancestorIt->GetSigOpCost();
752 assert(
it->GetCountWithAncestors() == nCountCheck);
753 assert(
it->GetSizeWithAncestors() == nSizeCheck);
754 assert(
it->GetSigOpCostWithAncestors() == nSigOpCheck);
755 assert(
it->GetModFeesWithAncestors() == nFeesCheck);
757 assert(prev_ancestor_count <= it->GetCountWithAncestors());
758 prev_ancestor_count =
it->GetCountWithAncestors();
762 auto iter = mapNextTx.lower_bound(
COutPoint(
it->GetTx().GetHash(), 0));
763 int32_t child_sizes{0};
764 for (; iter != mapNextTx.end() && iter->first->hash ==
it->GetTx().GetHash(); ++iter) {
765 txiter childit = mapTx.find(iter->second->GetHash());
766 assert(childit != mapTx.end());
767 if (setChildrenCheck.insert(*childit).second) {
768 child_sizes += childit->GetTxSize();
771 assert(setChildrenCheck.size() ==
it->GetMemPoolChildrenConst().size());
772 assert(std::equal(setChildrenCheck.begin(), setChildrenCheck.end(),
it->GetMemPoolChildrenConst().begin(), comp));
775 assert(
it->GetSizeWithDescendants() >= child_sizes +
it->GetTxSize());
781 for (
const auto& input: tx.
vin) mempoolDuplicate.SpendCoin(input.prevout);
782 AddCoins(mempoolDuplicate, tx, std::numeric_limits<int>::max());
784 for (
const auto& [
_, next_tx] : mapNextTx) {
785 auto it = mapTx.find(next_tx->GetHash());
791 assert(totalTxSize == checkTotal);
792 assert(m_total_fee == check_total_fee);
793 assert(innerUsage == cachedInnerUsage);
805 if (!j.has_value())
return false;
807 if (!i.has_value())
return true;
808 uint64_t counta = i.value()->GetCountWithAncestors();
809 uint64_t countb = j.value()->GetCountWithAncestors();
810 if (counta == countb) {
813 return counta < countb;
817class DepthAndScoreComparator
820 bool operator()(
const CTxMemPool::indexed_transaction_set::const_iterator& a,
const CTxMemPool::indexed_transaction_set::const_iterator& b)
822 uint64_t counta = a->GetCountWithAncestors();
823 uint64_t countb = b->GetCountWithAncestors();
824 if (counta == countb) {
827 return counta < countb;
834 std::vector<indexed_transaction_set::const_iterator> iters;
837 iters.reserve(mapTx.size());
839 for (indexed_transaction_set::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi) {
842 std::sort(iters.begin(), iters.end(), DepthAndScoreComparator());
850 std::vector<CTxMemPoolEntryRef>
ret;
851 ret.reserve(mapTx.size());
853 ret.emplace_back(*
it);
863 std::vector<TxMempoolInfo>
ret;
864 ret.reserve(mapTx.size());
865 for (
auto it : iters) {
875 const auto i = mapTx.find(txid);
876 return i == mapTx.end() ? nullptr : &(*i);
882 indexed_transaction_set::const_iterator i = mapTx.find(hash);
883 if (i == mapTx.end())
885 return i->GetSharedTx();
892 CAmount &delta = mapDeltas[hash];
895 if (
it != mapTx.end()) {
899 for (
txiter ancestorIt : ancestors) {
905 setDescendants.erase(
it);
906 for (
txiter descendantIt : setDescendants) {
912 mapDeltas.erase(hash);
913 LogPrintf(
"PrioritiseTransaction: %s (%sin mempool) delta cleared\n", hash.
ToString(),
it == mapTx.end() ?
"not " :
"");
915 LogPrintf(
"PrioritiseTransaction: %s (%sin mempool) fee += %s, new delta=%s\n",
917 it == mapTx.end() ?
"not " :
"",
927 std::map<Txid, CAmount>::const_iterator pos = mapDeltas.find(hash);
928 if (pos == mapDeltas.end())
930 const CAmount &delta = pos->second;
937 mapDeltas.erase(hash);
944 std::vector<delta_info> result;
945 result.reserve(mapDeltas.size());
946 for (
const auto& [txid, delta] : mapDeltas) {
947 const auto iter{mapTx.find(txid)};
948 const bool in_mempool{iter != mapTx.end()};
949 std::optional<CAmount> modified_fee;
950 if (in_mempool) modified_fee = iter->GetModifiedFee();
951 result.emplace_back(
delta_info{in_mempool, delta, modified_fee, txid});
958 const auto it = mapNextTx.find(prevout);
959 return it == mapNextTx.end() ? nullptr :
it->second;
965 auto it = mapTx.find(txid);
966 return it != mapTx.end() ? std::make_optional(
it) : std::nullopt;
973 return it != mapTx.end() ? std::make_optional(
it) : std::nullopt;
979 for (
const auto& h : hashes) {
981 if (mi)
ret.insert(*mi);
989 std::vector<txiter>
ret;
990 ret.reserve(txids.size());
991 for (
const auto& txid : txids) {
1001 for (
unsigned int i = 0; i < tx.
vin.size(); i++)
1022 if (outpoint.
n < ptx->vout.size()) {
1027 return std::nullopt;
1034 for (
unsigned int n = 0; n < tx->vout.size(); ++n) {
1054 if (m_unbroadcast_txids.erase(txid))
1056 LogDebug(
BCLog::MEMPOOL,
"Removed %i from set of unbroadcast txns%s\n", txid.
GetHex(), (unchecked ?
" before confirmation that txn was sent out" :
""));
1071 Assume(!m_have_changeset);
1072 indexed_transaction_set::index<entry_time>::type::iterator
it = mapTx.get<
entry_time>().begin();
1074 while (
it != mapTx.get<
entry_time>().end() &&
it->GetTime() < time) {
1075 toremove.insert(mapTx.project<0>(
it));
1079 for (
txiter removeit : toremove) {
1083 return stage.size();
1090 if (add && entry->GetMemPoolChildren().insert(*child).second) {
1092 }
else if (!add && entry->GetMemPoolChildren().erase(*child)) {
1101 if (add && entry->GetMemPoolParents().insert(*parent).second) {
1103 }
else if (!add && entry->GetMemPoolParents().erase(*parent)) {
1110 if (!blockSinceLastRollingFeeBump || rollingMinimumFeeRate == 0)
1111 return CFeeRate(llround(rollingMinimumFeeRate));
1114 if (time > lastRollingFeeUpdate + 10) {
1121 rollingMinimumFeeRate = rollingMinimumFeeRate / pow(2.0, (time - lastRollingFeeUpdate) / halflife);
1122 lastRollingFeeUpdate = time;
1125 rollingMinimumFeeRate = 0;
1134 if (rate.
GetFeePerK() > rollingMinimumFeeRate) {
1136 blockSinceLastRollingFeeBump =
false;
1142 Assume(!m_have_changeset);
1144 unsigned nTxnRemoved = 0;
1147 indexed_transaction_set::index<descendant_score>::type::iterator
it = mapTx.get<
descendant_score>().begin();
1153 CFeeRate removed(
it->GetModFeesWithDescendants(),
it->GetSizeWithDescendants());
1156 maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed);
1160 nTxnRemoved += stage.size();
1162 std::vector<CTransaction> txn;
1163 if (pvNoSpendsRemaining) {
1164 txn.reserve(stage.size());
1165 for (
txiter iter : stage)
1166 txn.push_back(iter->GetTx());
1169 if (pvNoSpendsRemaining) {
1173 pvNoSpendsRemaining->push_back(txin.
prevout);
1179 if (maxFeeRateRemoved >
CFeeRate(0)) {
1186 std::vector<txiter> candidates;
1188 candidates.push_back(entry);
1189 uint64_t maximum = 0;
1190 while (candidates.size()) {
1191 txiter candidate = candidates.back();
1192 candidates.pop_back();
1193 if (!counted.insert(candidate).second)
continue;
1195 if (parents.size() == 0) {
1196 maximum = std::max(maximum, candidate->GetCountWithDescendants());
1199 candidates.push_back(mapTx.iterator_to(i));
1208 auto it = mapTx.find(txid);
1209 ancestors = descendants = 0;
1210 if (
it != mapTx.end()) {
1211 ancestors =
it->GetCountWithAncestors();
1212 if (ancestorsize) *ancestorsize =
it->GetSizeWithAncestors();
1213 if (ancestorfees) *ancestorfees =
it->GetModFeesWithAncestors();
1221 return m_load_tried;
1227 m_load_tried = load_tried;
1233 std::vector<txiter> clustered_txs{
GetIterVec(txids)};
1237 for (
const auto&
it : clustered_txs) {
1241 for (
size_t i{0}; i < clustered_txs.size(); ++i) {
1243 if (clustered_txs.size() > 500)
return {};
1244 const txiter& tx_iter = clustered_txs.at(i);
1245 for (
const auto& entries : {tx_iter->GetMemPoolParentsConst(), tx_iter->GetMemPoolChildrenConst()}) {
1247 const auto entry_it = mapTx.iterator_to(entry);
1249 clustered_txs.push_back(entry_it);
1254 return clustered_txs;
1259 for (
const auto& direct_conflict : direct_conflicts) {
1261 const auto ancestor_count{direct_conflict->GetCountWithAncestors()};
1262 const auto descendant_count{direct_conflict->GetCountWithDescendants()};
1263 const bool has_ancestor{ancestor_count > 1};
1264 const bool has_descendant{descendant_count > 1};
1265 const auto& txid_string{direct_conflict->GetSharedTx()->GetHash().ToString()};
1270 if (ancestor_count > 2) {
1271 return strprintf(
"%s has %u ancestors, max 1 allowed", txid_string, ancestor_count - 1);
1272 }
else if (descendant_count > 2) {
1273 return strprintf(
"%s has %u descendants, max 1 allowed", txid_string, descendant_count - 1);
1274 }
else if (has_ancestor && has_descendant) {
1275 return strprintf(
"%s has both ancestor and descendant, exceeding cluster limit of 2", txid_string);
1280 if (has_descendant) {
1281 const auto& our_child = direct_conflict->GetMemPoolChildrenConst().begin();
1282 if (our_child->get().GetCountWithAncestors() > 2) {
1283 return strprintf(
"%s is not the only parent of child %s",
1284 txid_string, our_child->get().GetSharedTx()->GetHash().ToString());
1286 }
else if (has_ancestor) {
1287 const auto& our_parent = direct_conflict->GetMemPoolParentsConst().begin();
1288 if (our_parent->get().GetCountWithDescendants() > 2) {
1289 return strprintf(
"%s is not the only child of parent %s",
1290 txid_string, our_parent->get().GetSharedTx()->GetHash().ToString());
1294 return std::nullopt;
1300 FeeFrac replacement_feerate{0, 0};
1302 replacement_feerate += {
it->GetModifiedFee(),
it->GetTxSize()};
1306 if (err_string.has_value()) {
1320 std::vector<FeeFrac> old_chunks;
1329 if (
txiter->GetCountWithDescendants() > 1) {
1335 if (
txiter->GetCountWithAncestors() > 1) {
1338 FeeFrac package{
txiter->GetModFeesWithAncestors(),
static_cast<int32_t
>(
txiter->GetSizeWithAncestors())};
1339 if (individual >> package) {
1343 old_chunks.emplace_back(package);
1346 old_chunks.emplace_back(package - individual);
1347 old_chunks.emplace_back(individual);
1350 old_chunks.emplace_back(individual);
1355 std::sort(old_chunks.begin(), old_chunks.end(), std::greater());
1357 std::vector<FeeFrac> new_chunks;
1370 if (direct_conflict->GetMemPoolParentsConst().size() > 0) {
1381 new_chunks.emplace_back(replacement_feerate);
1384 std::sort(new_chunks.begin(), new_chunks.end(), std::greater());
1385 return std::make_pair(old_chunks, new_chunks);
1391 Assume(m_to_add.find(tx->GetHash()) == m_to_add.end());
1392 auto newit = m_to_add.emplace(tx,
fee, time, entry_height, entry_sequence, spends_coinbase, sigops_cost,
lp).first;
1394 m_pool->ApplyDelta(tx->GetHash(), delta);
1397 m_entry_vec.push_back(newit);
1404 m_pool->Apply(
this);
1406 m_to_remove.clear();
1407 m_entry_vec.clear();
1408 m_ancestors.clear();
int64_t CAmount
Amount in satoshis (Can be negative)
#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 Wtxid & GetWitnessHash() const LIFETIMEBOUND
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.