59 std::vector<CTxMemPoolEntry::CTxMemPoolEntryRef>
ret;
63 auto iter = mapNextTx.lower_bound(
COutPoint(hash, 0));
64 for (; iter != mapNextTx.end() && iter->first->hash == hash; ++iter) {
65 ret.emplace_back(*(iter->second));
69 auto removed = std::ranges::unique(
ret, [](
auto& a,
auto& b)
noexcept {
return &a.get() == &b.get(); });
70 ret.erase(removed.begin(), removed.end());
77 std::vector<CTxMemPoolEntry::CTxMemPoolEntryRef>
ret;
78 std::set<Txid> inputs;
79 for (
const auto& txin : entry.
GetTx().
vin) {
80 inputs.insert(txin.prevout.hash);
82 for (
const auto& hash : inputs) {
83 std::optional<txiter> piter =
GetIter(hash);
85 ret.emplace_back(**piter);
97 for (
const Txid& hash : vHashesToUpdate | std::views::reverse) {
99 txiter it = mapTx.find(hash);
100 if (it == mapTx.end()) {
103 auto iter = mapNextTx.lower_bound(
COutPoint(hash, 0));
105 for (; iter != mapNextTx.end() && iter->first->hash == hash; ++iter) {
106 txiter childIter = iter->second;
107 assert(childIter != mapTx.end());
110 m_txgraph->AddDependency(*it, *childIter);
115 auto txs_to_remove = m_txgraph->Trim();
116 for (
auto txptr : txs_to_remove) {
126 if (!entry)
return false;
134 if (ancestors.size() > 0) {
135 for (
auto ancestor : ancestors) {
136 if (ancestor != &entry) {
149 for (
unsigned int i = 0; i < tx.
vin.size(); i++) {
150 std::optional<txiter> piter =
GetIter(tx.
vin[i].prevout.hash);
152 staged_parents.insert(*piter);
156 for (
const auto& parent : staged_parents) {
158 for (
auto ancestor : parent_ancestors) {
168 opts.
check_ratio = std::clamp<int>(opts.check_ratio, 0, 1'000'000);
169 int64_t cluster_limit_bytes = opts.limits.cluster_size_vbytes * 40;
170 if (opts.max_size_bytes < 0 || (opts.max_size_bytes > 0 && opts.max_size_bytes < cluster_limit_bytes)) {
171 error =
strprintf(
_(
"-maxmempool must be at least %d MB"), std::ceil(cluster_limit_bytes / 1'000'000.0));
173 return std::move(opts);
184 const Txid& txid_a = static_cast<const CTxMemPoolEntry&>(a).GetTx().GetHash();
185 const Txid& txid_b = static_cast<const CTxMemPoolEntry&>(b).GetTx().GetHash();
186 return txid_a <=> txid_b;
193 return mapNextTx.count(outpoint);
209 m_txgraph->CommitStaging();
213 for (
size_t i=0; i<changeset->
m_entry_vec.size(); ++i) {
216 auto node_handle = changeset->
m_to_add.extract(tx_entry);
217 auto result = mapTx.insert(std::move(node_handle));
220 txiter it = result.position;
239 for (
unsigned int i = 0; i < tx.
vin.size(); i++) {
240 mapNextTx.insert(std::make_pair(&tx.
vin[i].prevout, newit));
251 m_total_fee += entry.
GetFee();
254 newit->idx_randomized = txns_randomized.size() - 1;
277 it->GetTx().GetHash().data(),
281 std::chrono::duration_cast<std::chrono::duration<std::uint64_t>>(it->GetTime()).count()
284 for (
const CTxIn& txin : it->GetTx().vin)
285 mapNextTx.erase(txin.prevout);
289 if (txns_randomized.size() > 1) {
291 txns_randomized[it->idx_randomized] = std::move(txns_randomized.back());
292 txns_randomized[it->idx_randomized].second->idx_randomized = it->idx_randomized;
293 txns_randomized.pop_back();
294 if (txns_randomized.size() * 2 < txns_randomized.capacity()) {
295 txns_randomized.shrink_to_fit();
298 txns_randomized.clear();
301 totalTxSize -= it->GetTxSize();
302 m_total_fee -= it->GetFee();
303 cachedInnerUsage -= it->DynamicMemoryUsage();
318 setDescendants.insert(mapTx.iterator_to(
static_cast<const CTxMemPoolEntry&
>(*tx)));
320 return mapTx.iterator_to(entry);
326 Assume(!m_have_changeset);
328 for (
auto tx: descendants) {
337 Assume(!m_have_changeset);
339 if (origit != mapTx.end()) {
347 std::vector<const TxGraph::Ref*> to_remove;
348 while (iter != mapNextTx.end() && iter->first->hash == origTx.
GetHash()) {
349 to_remove.emplace_back(&*(iter->second));
353 for (
auto ref : all_removes) {
354 auto tx = mapTx.iterator_to(
static_cast<const CTxMemPoolEntry&
>(*ref));
365 Assume(!m_have_changeset);
367 std::vector<const TxGraph::Ref*> to_remove;
368 for (
txiter it = mapTx.begin(); it != mapTx.end(); it++) {
369 if (check_final_and_mature(it)) {
370 to_remove.emplace_back(&*it);
376 for (
auto ref : all_to_remove) {
377 auto it = mapTx.iterator_to(
static_cast<const CTxMemPoolEntry&
>(*ref));
380 for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
393 auto it = mapNextTx.find(txin.
prevout);
394 if (it != mapNextTx.end()) {
409 Assume(!m_have_changeset);
410 std::vector<RemovedMempoolTransactionInfo> txs_removed_for_block;
411 if (mapTx.size() || mapNextTx.size() || mapDeltas.size()) {
412 txs_removed_for_block.reserve(vtx.size());
413 for (
const auto& tx : vtx) {
414 txiter it = mapTx.find(tx->GetHash());
415 if (it != mapTx.end()) {
416 txs_removed_for_block.emplace_back(*it);
426 lastRollingFeeUpdate =
GetTime();
427 blockSinceLastRollingFeeBump =
true;
441 LogDebug(
BCLog::MEMPOOL,
"Checking mempool with %u transactions and %u inputs\n", (
unsigned int)mapTx.size(), (
unsigned int)mapNextTx.size());
443 uint64_t checkTotal = 0;
445 CAmount check_total_modified_fee{0};
446 int64_t check_total_adjusted_weight{0};
447 uint64_t innerUsage = 0;
450 m_txgraph->SanityCheck();
458 assert(diagram.size() <= score_with_topo.size() + 1);
459 assert(diagram.size() >= 1);
461 std::optional<txiter> last_iter = std::nullopt;
462 auto diagram_iter = diagram.cbegin();
464 for (
const auto& it : score_with_topo) {
471 assert(diagram_iter->size >= check_total_adjusted_weight);
472 if (diagram_iter->fee == check_total_modified_fee &&
473 diagram_iter->size == check_total_adjusted_weight) {
476 checkTotal += it->GetTxSize();
477 check_total_adjusted_weight += it->GetAdjustedWeight();
478 check_total_fee += it->GetFee();
479 check_total_modified_fee += it->GetModifiedFee();
480 innerUsage += it->DynamicMemoryUsage();
484 assert(m_txgraph->CompareMainOrder(**last_iter, *it) < 0);
488 std::set<CTxMemPoolEntry::CTxMemPoolEntryRef, CompareIteratorByHash> setParentCheck;
489 std::set<CTxMemPoolEntry::CTxMemPoolEntryRef, CompareIteratorByHash> setParentsStored;
492 indexed_transaction_set::const_iterator it2 = mapTx.find(txin.
prevout.
hash);
493 if (it2 != mapTx.end()) {
496 setParentCheck.insert(*it2);
504 auto it3 = mapNextTx.find(txin.
prevout);
505 assert(it3 != mapNextTx.end());
507 assert(&it3->second->GetTx() == &tx);
513 setParentsStored.insert(
dynamic_cast<const CTxMemPoolEntry&
>(txentry.get()));
515 assert(setParentCheck.size() == setParentsStored.size());
516 assert(std::equal(setParentCheck.begin(), setParentCheck.end(), setParentsStored.begin(), comp));
519 std::set<CTxMemPoolEntry::CTxMemPoolEntryRef, CompareIteratorByHash> setChildrenCheck;
520 std::set<CTxMemPoolEntry::CTxMemPoolEntryRef, CompareIteratorByHash> setChildrenStored;
521 auto iter = mapNextTx.lower_bound(
COutPoint(it->GetTx().GetHash(), 0));
522 for (; iter != mapNextTx.end() && iter->first->hash == it->GetTx().GetHash(); ++iter) {
523 txiter childit = iter->second;
524 assert(childit != mapTx.end());
525 setChildrenCheck.insert(*childit);
528 setChildrenStored.insert(
dynamic_cast<const CTxMemPoolEntry&
>(txentry.get()));
530 assert(setChildrenCheck.size() == setChildrenStored.size());
531 assert(std::equal(setChildrenCheck.begin(), setChildrenCheck.end(), setChildrenStored.begin(), comp));
537 for (
const auto& input: tx.
vin) mempoolDuplicate.SpendCoin(input.prevout);
538 AddCoins(mempoolDuplicate, tx, std::numeric_limits<int>::max());
540 for (
auto it = mapNextTx.cbegin(); it != mapNextTx.cend(); it++) {
541 indexed_transaction_set::const_iterator it2 = it->second;
542 assert(it2 != mapTx.end());
546 assert(diagram_iter == diagram.cend());
548 assert(totalTxSize == checkTotal);
549 assert(m_total_fee == check_total_fee);
550 assert(diagram.back().fee == check_total_modified_fee);
551 assert(diagram.back().size == check_total_adjusted_weight);
552 assert(innerUsage == cachedInnerUsage);
572 auto cmp = [&](
const auto& a,
const auto& b)
EXCLUSIVE_LOCKS_REQUIRED(
cs)
noexcept {
return m_txgraph->CompareMainOrder(*a, *b) < 0; };
574 std::vector<txiter> res;
576 n_to_sort = std::min(wtxids.size(), n_to_sort);
578 res.reserve(wtxids.size());
579 std::sort(wtxids.begin(), wtxids.end());
580 for (
auto it = wtxids.begin(); it != wtxids.end(); ++it) {
582 auto itnext = it + 1;
583 if (itnext != wtxids.end() && *it == *itnext)
continue;
585 if (
auto i{
GetIter(*it)}; i.has_value()) {
586 res.push_back(i.value());
592 auto begin = res.begin();
593 auto end = res.end();
595 if (n_to_sort >= res.size()) {
597 std::sort(begin, end, cmp);
599 middle = begin + n_to_sort;
600 std::partial_sort(begin, middle, end, cmp);
604 wtxids.push_back((*it)->GetTx().GetWitnessHash());
607 res.erase(middle, end);
615 std::vector<indexed_transaction_set::const_iterator> iters;
618 iters.reserve(mapTx.size());
620 for (indexed_transaction_set::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi) {
624 return m_txgraph->CompareMainOrder(*a, *b) < 0;
633 std::vector<CTxMemPoolEntryRef>
ret;
634 ret.reserve(mapTx.size());
636 ret.emplace_back(*it);
646 std::vector<TxMempoolInfo>
ret;
647 ret.reserve(mapTx.size());
648 for (
auto it : iters) {
658 const auto i = mapTx.find(txid);
659 return i == mapTx.end() ? nullptr : &(*i);
665 indexed_transaction_set::const_iterator i = mapTx.find(hash);
666 if (i == mapTx.end())
668 return i->GetSharedTx();
675 const auto it{wtxid_map.find(hash)};
676 if (it == wtxid_map.end())
return nullptr;
677 return it->GetSharedTx();
684 CAmount &delta = mapDeltas[hash];
686 txiter it = mapTx.find(hash);
687 if (it != mapTx.end()) {
690 it->UpdateModifiedFee(nFeeDelta);
691 m_txgraph->SetTransactionFee(*it, it->GetModifiedFee());
695 mapDeltas.erase(hash);
696 LogInfo(
"PrioritiseTransaction: %s (%sin mempool) delta cleared\n", hash.
ToString(), it == mapTx.end() ?
"not " :
"");
698 LogInfo(
"PrioritiseTransaction: %s (%sin mempool) fee += %s, new delta=%s\n",
700 it == mapTx.end() ?
"not " :
"",
710 std::map<Txid, CAmount>::const_iterator pos = mapDeltas.find(hash);
711 if (pos == mapDeltas.end())
713 const CAmount &delta = pos->second;
720 mapDeltas.erase(hash);
727 std::vector<delta_info> result;
728 result.reserve(mapDeltas.size());
729 for (
const auto& [txid, delta] : mapDeltas) {
730 const auto iter{mapTx.find(txid)};
731 const bool in_mempool{iter != mapTx.end()};
732 std::optional<CAmount> modified_fee;
733 if (in_mempool) modified_fee = iter->GetModifiedFee();
734 result.emplace_back(
delta_info{in_mempool, delta, modified_fee, txid});
741 const auto it = mapNextTx.find(prevout);
742 return it == mapNextTx.end() ? nullptr : &(it->second->GetTx());
748 auto it = mapTx.find(txid);
749 return it != mapTx.end() ? std::make_optional(it) : std::nullopt;
755 auto it{mapTx.project<0>(mapTx.get<
index_by_wtxid>().find(wtxid))};
756 return it != mapTx.end() ? std::make_optional(it) : std::nullopt;
762 for (
const auto& h : hashes) {
764 if (mi)
ret.insert(*mi);
772 std::vector<txiter>
ret;
773 ret.reserve(txids.size());
774 for (
const auto& txid : txids) {
784 for (
unsigned int i = 0; i < tx.
vin.size(); i++)
805 if (outpoint.
n < ptx->vout.size()) {
817 for (
unsigned int n = 0; n < tx->vout.size(); ++n) {
837 if (m_unbroadcast_txids.erase(txid))
839 LogDebug(
BCLog::MEMPOOL,
"Removed %s from set of unbroadcast txns%s", txid.
GetHex(), (unchecked ?
" before confirmation that txn was sent out" :
""));
864 Assume(!m_have_changeset);
865 indexed_transaction_set::index<entry_time>::type::iterator it = mapTx.get<
entry_time>().begin();
867 while (it != mapTx.get<
entry_time>().end() && it->GetTime() < time) {
868 toremove.insert(mapTx.project<0>(it));
872 for (
txiter removeit : toremove) {
881 if (!blockSinceLastRollingFeeBump || rollingMinimumFeeRate == 0)
882 return CFeeRate(llround(rollingMinimumFeeRate));
885 if (time > lastRollingFeeUpdate + 10) {
892 rollingMinimumFeeRate = rollingMinimumFeeRate / pow(2.0, (time - lastRollingFeeUpdate) / halflife);
893 lastRollingFeeUpdate = time;
896 rollingMinimumFeeRate = 0;
905 if (rate.
GetFeePerK() > rollingMinimumFeeRate) {
907 blockSinceLastRollingFeeBump =
false;
913 Assume(!m_have_changeset);
915 unsigned nTxnRemoved = 0;
919 const auto &[worst_chunk, feeperweight] = m_txgraph->GetWorstMainChunk();
929 maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed);
931 nTxnRemoved += worst_chunk.size();
933 std::vector<CTransaction> txn;
934 if (pvNoSpendsRemaining) {
935 txn.reserve(worst_chunk.size());
936 for (
auto ref : worst_chunk) {
942 for (
auto ref : worst_chunk) {
943 stage.insert(mapTx.iterator_to(
static_cast<const CTxMemPoolEntry&
>(*ref)));
945 for (
auto e : stage) {
948 if (pvNoSpendsRemaining) {
952 pvNoSpendsRemaining->push_back(txin.
prevout);
958 if (maxFeeRateRemoved >
CFeeRate(0)) {
967 size_t ancestor_count = ancestors.size();
968 size_t ancestor_size = 0;
970 for (
auto tx: ancestors) {
975 return {ancestor_count, ancestor_size, ancestor_fees};
981 size_t descendant_count = descendants.size();
982 size_t descendant_size = 0;
985 for (
auto tx: descendants) {
990 return {descendant_count, descendant_size, descendant_fees};
995 auto it = mapTx.find(txid);
996 ancestors = cluster_count = 0;
997 if (it != mapTx.end()) {
999 ancestors = ancestor_count;
1000 if (ancestorsize) *ancestorsize = ancestor_size;
1001 if (ancestorfees) *ancestorfees = ancestor_fees;
1009 return m_load_tried;
1015 m_load_tried = load_tried;
1022 std::vector<CTxMemPool::txiter>
ret;
1023 std::set<const CTxMemPoolEntry*> unique_cluster_representatives;
1024 for (
auto txid : txids) {
1025 auto it = mapTx.find(txid);
1026 if (it != mapTx.end()) {
1031 if (unique_cluster_representatives.insert(
static_cast<const CTxMemPoolEntry*
>(&(**cluster.begin()))).second) {
1032 for (
auto tx : cluster) {
1038 if (
ret.size() > 500) {
1052 return m_pool->m_txgraph->GetMainStagingDiagrams();
1058 Assume(m_to_add.find(tx->GetHash()) == m_to_add.end());
1059 Assume(!m_dependencies_processed);
1062 m_dependencies_processed =
false;
1065 m_pool->ApplyDelta(tx->GetHash(), delta);
1068 auto newit = m_to_add.emplace(tx,
fee, time, entry_height, entry_sequence, spends_coinbase, sigops_cost,
lp).first;
1069 m_pool->m_txgraph->AddTransaction(
const_cast<CTxMemPoolEntry&
>(*newit), feerate);
1071 newit->UpdateModifiedFee(delta);
1072 m_pool->m_txgraph->SetTransactionFee(*newit, newit->GetModifiedFee());
1075 m_entry_vec.push_back(newit);
1083 m_pool->m_txgraph->RemoveTransaction(*it);
1084 m_to_remove.insert(it);
1090 if (!m_dependencies_processed) {
1091 ProcessDependencies();
1093 m_pool->Apply(
this);
1095 m_to_remove.clear();
1096 m_entry_vec.clear();
1097 m_ancestors.clear();
1103 Assume(!m_dependencies_processed);
1104 for (
const auto& entryptr : m_entry_vec) {
1105 for (
const auto &txin : entryptr->GetSharedTx()->vin) {
1106 std::optional<txiter> piter = m_pool->GetIter(txin.
prevout.
hash);
1109 if (it != m_to_add.end()) {
1110 piter = std::make_optional(it);
1114 m_pool->m_txgraph->AddDependency(**piter, *entryptr);
1118 m_dependencies_processed =
true;
1125 if (!m_dependencies_processed) {
1126 ProcessDependencies();
1135 std::vector<FeePerWeight>
ret;
1137 ret.emplace_back(zero);
1141 std::vector<CTxMemPoolEntry::CTxMemPoolEntryRef> dummy;
1145 last_selection +=
ret.back();
1146 ret.emplace_back(last_selection);
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 &index) 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.
Pure abstract view on the open txout dataset.
virtual std::optional< Coin > GetCoin(const COutPoint &outpoint) const =0
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(FeeRateFormat fee_rate_format=FeeRateFormat::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)
void StageRemoval(CTxMemPool::txiter it)
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
TxHandle StageAddition(const CTransactionRef &tx, CAmount fee, int64_t time, unsigned int entry_height, uint64_t entry_sequence, bool spends_coinbase, int64_t sigops_cost, LockPoints lp)
bool CheckMemPoolPolicyLimits()
Check if any cluster limits are exceeded.
void ProcessDependencies()
std::vector< CTxMemPool::txiter > m_entry_vec
CTxMemPoolEntry stores data about the corresponding transaction, as well as data about all in-mempool...
const CTransaction & GetTx() const
size_t DynamicMemoryUsage() const
int32_t GetTxSize() const
const CAmount & GetFee() const
CAmount GetModifiedFee() const
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.
std::unique_ptr< ChangeSet > GetChangeSet() EXCLUSIVE_LOCKS_REQUIRED(cs)
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)
std::optional< txiter > GetIter(const Txid &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Returns an iterator to the given hash, if found.
bool GetLoadTried() const
void StopBlockBuilding() const EXCLUSIVE_LOCKS_REQUIRED(cs)
CFeeRate GetMinFee() const
The minimum fee to get into the mempool, which may itself not be enough for larger-sized transactions...
void trackPackageRemoved(const CFeeRate &rate) EXCLUSIVE_LOCKS_REQUIRED(cs)
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 GetTransactionAncestry(const Txid &txid, size_t &ancestors, size_t &cluster_count, size_t *ancestorsize=nullptr, CAmount *ancestorfees=nullptr) const
Calculate the ancestor and cluster count for the given transaction.
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)
bool HasDescendants(const Txid &txid) const
std::vector< indexed_transaction_set::const_iterator > GetSortedScoreWithTopology() const EXCLUSIVE_LOCKS_REQUIRED(cs)
void StartBlockBuilding() const EXCLUSIVE_LOCKS_REQUIRED(cs)
CTransactionRef get(const Txid &hash) const
Return a mempool transaction with a given hash.
size_t DynamicMemoryUsage() const
std::vector< TxMempoolInfo > infoAll() const
static constexpr int ROLLING_FEE_HALFLIFE
CTxMemPool(Options opts, bilingual_str &error)
Create a new CTxMemPool.
void addNewTransaction(CTxMemPool::txiter it) EXCLUSIVE_LOCKS_REQUIRED(cs)
void removeUnchecked(txiter entry, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
int Expire(std::chrono::seconds time) EXCLUSIVE_LOCKS_REQUIRED(cs)
Expire all transaction (and their dependencies) in the mempool older than time.
void IncludeBuilderChunk() const EXCLUSIVE_LOCKS_REQUIRED(cs)
void removeForReorg(CChain &chain, std::function< bool(txiter)> filter_final_and_mature) EXCLUSIVE_LOCKS_REQUIRED(cs
After reorg, filter the entries that would no longer be valid in the next block, and update the entri...
std::vector< FeePerWeight > GetFeerateDiagram() const EXCLUSIVE_LOCKS_REQUIRED(cs)
std::tuple< size_t, size_t, CAmount > CalculateDescendantData(const CTxMemPoolEntry &entry) const EXCLUSIVE_LOCKS_REQUIRED(cs)
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.
std::set< txiter, CompareIteratorByHash > setEntries
std::vector< CTxMemPoolEntry::CTxMemPoolEntryRef > GetParents(const CTxMemPoolEntry &entry) const
void ApplyDelta(const Txid &hash, CAmount &nFeeDelta) const EXCLUSIVE_LOCKS_REQUIRED(cs)
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.
bool CheckPolicyLimits(const CTransactionRef &tx)
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 given transaction.
std::tuple< size_t, size_t, CAmount > CalculateAncestorData(const CTxMemPoolEntry &entry) const EXCLUSIVE_LOCKS_REQUIRED(cs)
std::vector< CTxMemPoolEntry::CTxMemPoolEntryRef > GetChildren(const CTxMemPoolEntry &entry) const
setEntries CalculateMemPoolAncestors(const CTxMemPoolEntry &entry) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Calculate all in-mempool ancestors of entry (not including the tx itself)
void RemoveUnbroadcastTx(const Txid &txid, bool unchecked=false)
Removes a transaction from the unbroadcast set.
std::vector< txiter > ExtractBestByMiningScoreWithTopology(std::vector< Wtxid > &wtxids, size_t n_to_sort) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Look up wtxids in the mempool and (partially) sort by mining score.
void SetLoadTried(bool load_tried)
Set whether or not an initial attempt to load the persisted mempool was made (regardless of whether t...
void RemoveStaged(setEntries &stage, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
Remove a set of transactions from the mempool.
std::vector< CTxMemPoolEntryRef > entryAll() const EXCLUSIVE_LOCKS_REQUIRED(cs)
bool isSpent(const COutPoint &outpoint) const
FeePerWeight GetBlockBuilderChunk(std::vector< CTxMemPoolEntry::CTxMemPoolEntryRef > &entries) const EXCLUSIVE_LOCKS_REQUIRED(cs)
const CTxMemPoolEntry * GetEntry(const Txid &txid) const LIFETIMEBOUND EXCLUSIVE_LOCKS_REQUIRED(cs)
unsigned int GetTransactionsUpdated() const
@ MAIN
Always refers to the main graph, whether staging is present or not.
@ TOP
Refers to staging if it exists, main otherwise.
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.
static int32_t GetTransactionWeight(const CTransaction &tx)
static const int WITNESS_SCALE_FACTOR
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
#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 MallocUsage(size_t alloc)
Compute the total memory used by allocating alloc bytes.
T SaturatingAdd(const T i, const T j) noexcept
unsigned int nBytesPerSigOp
int64_t GetSigOpsAdjustedWeight(int64_t weight, int64_t sigop_cost, unsigned int bytes_per_sigop)
static FeePerVSize ToFeePerVSize(FeePerWeight feerate)
std::shared_ptr< const CTransaction > CTransactionRef
CBlockIndex * maxInputBlock
unsigned cluster_count
The maximum number of transactions in a cluster.
int64_t cluster_size_vbytes
The maximum allowed size in virtual bytes of a cluster.
Options struct containing options for constructing a CTxMemPool.
ValidationSignals * signals
CFeeRate incremental_relay_feerate
#define AssertLockNotHeld(cs)
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define TRACEPOINT(context,...)
consteval auto _(util::TranslatedLiteral str)
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
std::unique_ptr< TxGraph > MakeTxGraph(unsigned max_cluster_count, uint64_t max_cluster_size, uint64_t acceptable_cost, const std::function< std::strong_ordering(const TxGraph::Ref &, const TxGraph::Ref &)> &fallback_order) noexcept
Construct a new TxGraph with the specified limit on the number of transactions within a cluster,...
static CTxMemPool::Options && Flatten(CTxMemPool::Options &&opts, bilingual_str &error)
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 constexpr uint64_t ACCEPTABLE_COST
How much linearization cost required for TxGraph clusters to have "acceptable" quality,...
static constexpr uint64_t POST_CHANGE_COST
How much work we ask TxGraph to do after a mempool change occurs (either due to a changeset being app...
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.