58 const std::set<uint256>& setExclude, std::set<uint256>& 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<uint256> setAlreadyIncluded(vHashesToUpdate.begin(), vHashesToUpdate.end());
120 std::set<uint256> descendants_to_remove;
127 for (
const uint256& hash : vHashesToUpdate | std::views::reverse) {
130 if (
it == mapTx.end()) {
139 for (; iter != mapNextTx.end() && iter->first->hash == hash; ++iter) {
140 const uint256 &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()) {
655 if (txConflict != tx)
670 Assume(!m_have_changeset);
671 std::vector<RemovedMempoolTransactionInfo> txs_removed_for_block;
672 txs_removed_for_block.reserve(vtx.size());
673 for (
const auto& tx : vtx)
675 txiter it = mapTx.find(tx->GetHash());
676 if (
it != mapTx.end()) {
679 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 (
auto it = mapNextTx.cbegin();
it != mapNextTx.cend();
it++) {
786 indexed_transaction_set::const_iterator it2 = mapTx.find(hash);
788 assert(it2 != mapTx.end());
792 assert(totalTxSize == checkTotal);
793 assert(m_total_fee == check_total_fee);
794 assert(innerUsage == cachedInnerUsage);
805 indexed_transaction_set::const_iterator j = wtxid ?
get_iter_from_wtxid(hashb) : mapTx.find(hashb);
806 if (j == mapTx.end())
return false;
807 indexed_transaction_set::const_iterator i = wtxid ?
get_iter_from_wtxid(hasha) : mapTx.find(hasha);
808 if (i == mapTx.end())
return true;
809 uint64_t counta = i->GetCountWithAncestors();
810 uint64_t countb = j->GetCountWithAncestors();
811 if (counta == countb) {
814 return counta < countb;
818class DepthAndScoreComparator
821 bool operator()(
const CTxMemPool::indexed_transaction_set::const_iterator& a,
const CTxMemPool::indexed_transaction_set::const_iterator& b)
823 uint64_t counta = a->GetCountWithAncestors();
824 uint64_t countb = b->GetCountWithAncestors();
825 if (counta == countb) {
828 return counta < countb;
835 std::vector<indexed_transaction_set::const_iterator> iters;
838 iters.reserve(mapTx.size());
840 for (indexed_transaction_set::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi) {
843 std::sort(iters.begin(), iters.end(), DepthAndScoreComparator());
848 return TxMempoolInfo{it->GetSharedTx(), it->GetTime(), it->GetFee(), it->GetTxSize(), it->GetModifiedFee() - it->GetFee()};
855 std::vector<CTxMemPoolEntryRef>
ret;
856 ret.reserve(mapTx.size());
858 ret.emplace_back(*
it);
868 std::vector<TxMempoolInfo>
ret;
869 ret.reserve(mapTx.size());
870 for (
auto it : iters) {
880 const auto i = mapTx.find(txid);
881 return i == mapTx.end() ? nullptr : &(*i);
887 indexed_transaction_set::const_iterator i = mapTx.find(hash);
888 if (i == mapTx.end())
890 return i->GetSharedTx();
897 if (i == mapTx.end())
906 if (i != mapTx.end() && i->GetSequence() < last_sequence) {
917 CAmount &delta = mapDeltas[hash];
920 if (
it != mapTx.end()) {
924 for (
txiter ancestorIt : ancestors) {
930 setDescendants.erase(
it);
931 for (
txiter descendantIt : setDescendants) {
937 mapDeltas.erase(hash);
938 LogPrintf(
"PrioritiseTransaction: %s (%sin mempool) delta cleared\n", hash.
ToString(),
it == mapTx.end() ?
"not " :
"");
940 LogPrintf(
"PrioritiseTransaction: %s (%sin mempool) fee += %s, new delta=%s\n",
942 it == mapTx.end() ?
"not " :
"",
952 std::map<uint256, CAmount>::const_iterator pos = mapDeltas.find(hash);
953 if (pos == mapDeltas.end())
955 const CAmount &delta = pos->second;
962 mapDeltas.erase(hash);
969 std::vector<delta_info> result;
970 result.reserve(mapDeltas.size());
971 for (
const auto& [txid, delta] : mapDeltas) {
972 const auto iter{mapTx.find(txid)};
973 const bool in_mempool{iter != mapTx.end()};
974 std::optional<CAmount> modified_fee;
975 if (in_mempool) modified_fee = iter->GetModifiedFee();
976 result.emplace_back(
delta_info{in_mempool, delta, modified_fee, txid});
983 const auto it = mapNextTx.find(prevout);
984 return it == mapNextTx.end() ? nullptr :
it->second;
989 auto it = mapTx.find(txid);
990 if (
it != mapTx.end())
return it;
997 for (
const auto& h : hashes) {
999 if (mi)
ret.insert(*mi);
1007 std::vector<txiter>
ret;
1008 ret.reserve(txids.size());
1009 for (
const auto& txid : txids) {
1019 for (
unsigned int i = 0; i < tx.
vin.size(); i++)
1040 if (outpoint.
n < ptx->vout.size()) {
1045 return std::nullopt;
1052 for (
unsigned int n = 0; n < tx->vout.size(); ++n) {
1072 if (m_unbroadcast_txids.erase(txid))
1074 LogDebug(
BCLog::MEMPOOL,
"Removed %i from set of unbroadcast txns%s\n", txid.
GetHex(), (unchecked ?
" before confirmation that txn was sent out" :
""));
1089 Assume(!m_have_changeset);
1090 indexed_transaction_set::index<entry_time>::type::iterator
it = mapTx.get<
entry_time>().begin();
1092 while (
it != mapTx.get<
entry_time>().end() &&
it->GetTime() < time) {
1093 toremove.insert(mapTx.project<0>(
it));
1097 for (
txiter removeit : toremove) {
1101 return stage.size();
1108 if (add && entry->GetMemPoolChildren().insert(*child).second) {
1110 }
else if (!add && entry->GetMemPoolChildren().erase(*child)) {
1119 if (add && entry->GetMemPoolParents().insert(*parent).second) {
1121 }
else if (!add && entry->GetMemPoolParents().erase(*parent)) {
1128 if (!blockSinceLastRollingFeeBump || rollingMinimumFeeRate == 0)
1129 return CFeeRate(llround(rollingMinimumFeeRate));
1132 if (time > lastRollingFeeUpdate + 10) {
1139 rollingMinimumFeeRate = rollingMinimumFeeRate / pow(2.0, (time - lastRollingFeeUpdate) / halflife);
1140 lastRollingFeeUpdate = time;
1143 rollingMinimumFeeRate = 0;
1152 if (rate.
GetFeePerK() > rollingMinimumFeeRate) {
1154 blockSinceLastRollingFeeBump =
false;
1160 Assume(!m_have_changeset);
1162 unsigned nTxnRemoved = 0;
1165 indexed_transaction_set::index<descendant_score>::type::iterator
it = mapTx.get<
descendant_score>().begin();
1171 CFeeRate removed(
it->GetModFeesWithDescendants(),
it->GetSizeWithDescendants());
1174 maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed);
1178 nTxnRemoved += stage.size();
1180 std::vector<CTransaction> txn;
1181 if (pvNoSpendsRemaining) {
1182 txn.reserve(stage.size());
1183 for (
txiter iter : stage)
1184 txn.push_back(iter->GetTx());
1187 if (pvNoSpendsRemaining) {
1191 pvNoSpendsRemaining->push_back(txin.
prevout);
1197 if (maxFeeRateRemoved >
CFeeRate(0)) {
1204 std::vector<txiter> candidates;
1206 candidates.push_back(entry);
1207 uint64_t maximum = 0;
1208 while (candidates.size()) {
1209 txiter candidate = candidates.back();
1210 candidates.pop_back();
1211 if (!counted.insert(candidate).second)
continue;
1213 if (parents.size() == 0) {
1214 maximum = std::max(maximum, candidate->GetCountWithDescendants());
1217 candidates.push_back(mapTx.iterator_to(i));
1226 auto it = mapTx.find(txid);
1227 ancestors = descendants = 0;
1228 if (
it != mapTx.end()) {
1229 ancestors =
it->GetCountWithAncestors();
1230 if (ancestorsize) *ancestorsize =
it->GetSizeWithAncestors();
1231 if (ancestorfees) *ancestorfees =
it->GetModFeesWithAncestors();
1239 return m_load_tried;
1245 m_load_tried = load_tried;
1251 std::vector<txiter> clustered_txs{
GetIterVec(txids)};
1255 for (
const auto&
it : clustered_txs) {
1259 for (
size_t i{0}; i < clustered_txs.size(); ++i) {
1261 if (clustered_txs.size() > 500)
return {};
1262 const txiter& tx_iter = clustered_txs.at(i);
1263 for (
const auto& entries : {tx_iter->GetMemPoolParentsConst(), tx_iter->GetMemPoolChildrenConst()}) {
1265 const auto entry_it = mapTx.iterator_to(entry);
1267 clustered_txs.push_back(entry_it);
1272 return clustered_txs;
1277 for (
const auto& direct_conflict : direct_conflicts) {
1279 const auto ancestor_count{direct_conflict->GetCountWithAncestors()};
1280 const auto descendant_count{direct_conflict->GetCountWithDescendants()};
1281 const bool has_ancestor{ancestor_count > 1};
1282 const bool has_descendant{descendant_count > 1};
1283 const auto& txid_string{direct_conflict->GetSharedTx()->GetHash().ToString()};
1288 if (ancestor_count > 2) {
1289 return strprintf(
"%s has %u ancestors, max 1 allowed", txid_string, ancestor_count - 1);
1290 }
else if (descendant_count > 2) {
1291 return strprintf(
"%s has %u descendants, max 1 allowed", txid_string, descendant_count - 1);
1292 }
else if (has_ancestor && has_descendant) {
1293 return strprintf(
"%s has both ancestor and descendant, exceeding cluster limit of 2", txid_string);
1298 if (has_descendant) {
1299 const auto& our_child = direct_conflict->GetMemPoolChildrenConst().begin();
1300 if (our_child->get().GetCountWithAncestors() > 2) {
1301 return strprintf(
"%s is not the only parent of child %s",
1302 txid_string, our_child->get().GetSharedTx()->GetHash().ToString());
1304 }
else if (has_ancestor) {
1305 const auto& our_parent = direct_conflict->GetMemPoolParentsConst().begin();
1306 if (our_parent->get().GetCountWithDescendants() > 2) {
1307 return strprintf(
"%s is not the only child of parent %s",
1308 txid_string, our_parent->get().GetSharedTx()->GetHash().ToString());
1312 return std::nullopt;
1318 FeeFrac replacement_feerate{0, 0};
1320 replacement_feerate += {
it->GetModifiedFee(),
it->GetTxSize()};
1324 if (err_string.has_value()) {
1338 std::vector<FeeFrac> old_chunks;
1347 if (
txiter->GetCountWithDescendants() > 1) {
1353 if (
txiter->GetCountWithAncestors() > 1) {
1356 FeeFrac package{
txiter->GetModFeesWithAncestors(),
static_cast<int32_t
>(
txiter->GetSizeWithAncestors())};
1357 if (individual >> package) {
1361 old_chunks.emplace_back(package);
1364 old_chunks.emplace_back(package - individual);
1365 old_chunks.emplace_back(individual);
1368 old_chunks.emplace_back(individual);
1373 std::sort(old_chunks.begin(), old_chunks.end(), std::greater());
1375 std::vector<FeeFrac> new_chunks;
1388 if (direct_conflict->GetMemPoolParentsConst().size() > 0) {
1399 new_chunks.emplace_back(replacement_feerate);
1402 std::sort(new_chunks.begin(), new_chunks.end(), std::greater());
1403 return std::make_pair(old_chunks, new_chunks);
1409 Assume(m_to_add.find(tx->GetHash()) == m_to_add.end());
1410 auto newit = m_to_add.emplace(tx,
fee, time, entry_height, entry_sequence, spends_coinbase, sigops_cost,
lp).first;
1412 m_pool->ApplyDelta(tx->GetHash(), delta);
1415 m_entry_vec.push_back(newit);
1422 m_pool->Apply(
this);
1424 m_to_remove.clear();
1425 m_entry_vec.clear();
1426 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 kilovirtualbyte: CAmount / kvB.
std::string ToString(const FeeEstimateMode &fee_estimate_mode=FeeEstimateMode::BTC_KVB) const
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
An outpoint - a combination of a transaction hash and an index n into its vout.
The basic transaction that is broadcasted on the network and contained in blocks.
const 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 RemoveUnbroadcastTx(const uint256 &txid, const bool unchecked=false)
Removes a transaction from the unbroadcast set.
void Apply(CTxMemPool::ChangeSet *changeset) EXCLUSIVE_LOCKS_REQUIRED(cs)
void PrioritiseTransaction(const uint256 &hash, const CAmount &nFeeDelta)
Affect CreateNewBlock prioritisation of transactions.
setEntries AssumeCalculateMemPoolAncestors(std::string_view calling_fn_name, const CTxMemPoolEntry &entry, const Limits &limits, bool fSearchForParents=true) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Same as CalculateMemPoolAncestors, but always returns a (non-optional) setEntries.
bool HasNoInputsOf(const CTransaction &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Check that none of this transactions inputs are in the mempool, and thus the tx is not dependent on o...
setEntries GetIterSet(const std::set< Txid > &hashes) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Translate a set of hashes into a set of pool iterators to avoid repeated lookups.
std::vector< txiter > GetIterVec(const std::vector< uint256 > &txids) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Translate a list of hashes into a list of mempool iterators to avoid repeated lookups.
void UpdateEntryForAncestors(txiter it, const setEntries &setAncestors) EXCLUSIVE_LOCKS_REQUIRED(cs)
Set ancestor state for an entry.
bool GetLoadTried() const
bool visited(const txiter it) const EXCLUSIVE_LOCKS_REQUIRED(cs
visited marks a CTxMemPoolEntry as having been traversed during the lifetime of the most recently cre...
CFeeRate GetMinFee() const
The minimum fee to get into the mempool, which may itself not be enough for larger-sized transactions...
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
void ClearPrioritisation(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs)
void trackPackageRemoved(const CFeeRate &rate) EXCLUSIVE_LOCKS_REQUIRED(cs)
util::Result< setEntries > CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, const Limits &limits, bool fSearchForParents=true) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Try to calculate all in-mempool ancestors of entry.
void 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 TrimToSize(size_t sizelimit, std::vector< COutPoint > *pvNoSpendsRemaining=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs)
Remove transactions from the mempool until its dynamic size is <= sizelimit.
void UpdateTransactionsFromBlock(const std::vector< uint256 > &vHashesToUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs
UpdateTransactionsFromBlock is called when adding transactions from a disconnected block back to the ...
void AddTransactionsUpdated(unsigned int n)
void UpdateChildrenForRemoval(txiter entry) EXCLUSIVE_LOCKS_REQUIRED(cs)
Sever link between specified transaction and direct children.
std::optional< txiter > GetIter(const uint256 &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Returns an iterator to the given hash, if found.
util::Result< setEntries > CalculateAncestorsAndCheckLimits(int64_t entry_size, size_t entry_count, CTxMemPoolEntry::Parents &staged_ancestors, const Limits &limits) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Helper function to calculate all in-mempool ancestors of staged_ancestors and apply ancestor and desc...
CTransactionRef get(const uint256 &hash) const
size_t DynamicMemoryUsage() const
std::vector< TxMempoolInfo > infoAll() const
void GetTransactionAncestry(const uint256 &txid, size_t &ancestors, size_t &descendants, size_t *ancestorsize=nullptr, CAmount *ancestorfees=nullptr) const
Calculate the ancestor and descendant count for the given transaction.
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 ...
int Expire(std::chrono::seconds time) EXCLUSIVE_LOCKS_REQUIRED(cs)
Expire all transaction (and their dependencies) in the mempool older than time.
txiter get_iter_from_wtxid(const uint256 &wtxid) const EXCLUSIVE_LOCKS_REQUIRED(cs)
void UpdateAncestorsOf(bool add, txiter hash, setEntries &setAncestors) EXCLUSIVE_LOCKS_REQUIRED(cs)
Update ancestors of hash to add/remove it as a descendant transaction.
void removeForReorg(CChain &chain, std::function< bool(txiter)> filter_final_and_mature) EXCLUSIVE_LOCKS_REQUIRED(cs
After reorg, filter the entries that would no longer be valid in the next block, and update the entri...
util::Result< void > CheckPackageLimits(const Package &package, int64_t total_vsize) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Calculate all in-mempool ancestors of a set of transactions not already in the mempool and check ance...
TxMempoolInfo info(const GenTxid >xid) const
std::vector< txiter > GatherClusters(const std::vector< uint256 > &txids) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Collect the entire cluster of connected transactions for each transaction in txids.
void ApplyDelta(const uint256 &hash, CAmount &nFeeDelta) const EXCLUSIVE_LOCKS_REQUIRED(cs)
void UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendants, const std::set< uint256 > &setExclude, std::set< uint256 > &descendants_to_remove) EXCLUSIVE_LOCKS_REQUIRED(cs)
UpdateForDescendants is used by UpdateTransactionsFromBlock to update the descendants for a single tr...
static const int ROLLING_FEE_HALFLIFE
std::set< txiter, CompareIteratorByHash > setEntries
std::vector< indexed_transaction_set::const_iterator > GetSortedDepthAndScore() const EXCLUSIVE_LOCKS_REQUIRED(cs)
void RemoveStaged(setEntries &stage, bool updateDescendants, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
Remove a set of transactions from the mempool.
void removeForBlock(const std::vector< CTransactionRef > &vtx, unsigned int nBlockHeight) EXCLUSIVE_LOCKS_REQUIRED(cs)
Called when a block is connected.
std::vector< delta_info > GetPrioritisedTransactions() const EXCLUSIVE_LOCKS_REQUIRED(!cs)
Return a vector of all entries in mapDeltas with their corresponding delta_info.
indexed_transaction_set::nth_index< 0 >::type::const_iterator txiter
uint64_t GetAndIncrementSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs)
Guards this internal counter for external reporting.
void UpdateChild(txiter entry, txiter child, bool add) EXCLUSIVE_LOCKS_REQUIRED(cs)
TxMempoolInfo info_for_relay(const GenTxid >xid, uint64_t last_sequence) const
Returns info for a transaction if its entry_sequence < last_sequence.
bool exists(const GenTxid >xid) const
std::map< txiter, setEntries, CompareIteratorByHash > cacheMap
const CTransaction * GetConflictTx(const COutPoint &prevout) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Get the transaction in the pool that spends the same prevout.
bool CompareDepthAndScore(const uint256 &hasha, const uint256 &hashb, bool wtxid=false)
void CalculateDescendants(txiter it, setEntries &setDescendants) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Populate setDescendants with all in-mempool descendants of hash.
std::optional< std::string > CheckConflictTopology(const setEntries &direct_conflicts)
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,...
A generic txid reference (txid or wtxid).
const uint256 & GetHash() const LIFETIMEBOUND
static GenTxid Txid(const uint256 &hash)
void MempoolTransactionsRemovedForBlock(const std::vector< RemovedMempoolTransactionInfo > &, unsigned int nBlockHeight)
void TransactionRemovedFromMempool(const CTransactionRef &, MemPoolRemovalReason, uint64_t mempool_sequence)
std::string ToString() const
std::string GetHex() const
constexpr const std::byte * data() const
static transaction_identifier FromUint256(const uint256 &id)
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
Information about a mempool transaction.
Options struct containing limit options for a CTxMemPool.
static constexpr MemPoolLimits NoLimits()
int64_t descendant_count
The maximum allowed number of transactions in a package including the entry and its descendants.
int64_t descendant_size_vbytes
The maximum allowed size in virtual bytes of an entry and its descendants within a package.
int64_t ancestor_count
The maximum allowed number of transactions in a package including the entry and its ancestors.
int64_t ancestor_size_vbytes
The maximum allowed size in virtual bytes of an entry and its ancestors within a package.
Options struct containing options for constructing a CTxMemPool.
ValidationSignals * signals
CFeeRate incremental_relay_feerate
#define AssertLockNotHeld(cs)
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
#define TRACEPOINT(context,...)
bilingual_str _(ConstevalStringLiteral str)
Translation function.
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 TxMempoolInfo GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it)
static const uint32_t MEMPOOL_HEIGHT
Fake height value used in Coin to signify they are only in the memory pool (since 0....