Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
501uint64_t GetTotalTxSize() const EXCLUSIVE_LOCKS_REQUIRED(cs)502{503AssertLockHeld(cs);504return totalTxSize;505}507CAmount GetTotalFee() const EXCLUSIVE_LOCKS_REQUIRED(cs)508{509AssertLockHeld(cs);510return m_total_fee;511}513bool exists(const Txid& txid) const514{515LOCK(cs);516return (mapTx.count(txid) != 0);517}519bool exists(const Wtxid& wtxid) const520{521LOCK(cs);522return (mapTx.get<index_by_wtxid>().count(wtxid) != 0);523}525const CTxMemPoolEntry* GetEntry(const Txid& txid) const LIFETIMEBOUND EXCLUSIVE_LOCKS_REQUIRED(cs);527/**528* Return a mempool transaction with a given hash.529*530* @param[in] hash the txid531* @returns the tx if found, otherwise nullptr532*/533CTransactionRef get(const Txid& hash) const;535/**536* Return a mempool transaction with a given witness hash.537*538* @param[in] hash the wtxid539* @returns the tx if found, otherwise nullptr540*/541CTransactionRef get(const Wtxid& hash) const;543template <TxidOrWtxid T>544TxMempoolInfo info(const T& id) const545{546LOCK(cs);547auto i{GetIter(id)};548return i.has_value() ? GetInfo(*i) : TxMempoolInfo{};549}551/** Returns info for a transaction if its entry_sequence < last_sequence */552template <TxidOrWtxid T>553TxMempoolInfo info_for_relay(const T& id, uint64_t last_sequence) const554{555LOCK(cs);556auto i{GetIter(id)};557return (i.has_value() && i.value()->GetSequence() < last_sequence) ? GetInfo(*i) : TxMempoolInfo{};558}560std::vector<CTxMemPoolEntryRef> entryAll() const EXCLUSIVE_LOCKS_REQUIRED(cs);561std::vector<TxMempoolInfo> infoAll() const;563size_t DynamicMemoryUsage() const;565/** Adds a transaction to the unbroadcast set */566void AddUnbroadcastTx(const Txid& txid)567{568LOCK(cs);569// Sanity check the transaction is in the mempool & insert into570// unbroadcast set.571if (exists(txid)) m_unbroadcast_txids.insert(txid);572};574bool CheckPolicyLimits(const CTransactionRef& tx);576/** Removes a transaction from the unbroadcast set */577void RemoveUnbroadcastTx(const Txid& txid, bool unchecked = false);579/** Returns transactions in unbroadcast set */580std::set<Txid> GetUnbroadcastTxs() const581{582LOCK(cs);583return m_unbroadcast_txids;584}586/** Returns whether a txid is in the unbroadcast set */587bool IsUnbroadcastTx(const Txid& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs)588{589AssertLockHeld(cs);590return m_unbroadcast_txids.contains(txid);591}593/** Guards this internal counter for external reporting */594uint64_t GetAndIncrementSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs) {595return m_sequence_number++;596}598uint64_t GetSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs) {599return m_sequence_number;600}602private:603/** Remove a set of transactions from the mempool.604* If a transaction is in this set, then all in-mempool descendants must605* also be in the set, unless this transaction is being removed for being606* in a block.607*/608void RemoveStaged(setEntries& stage, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs);610/* Helper for the public removeRecursive() */611void removeRecursive(txiter to_remove, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs);613/* Removal from the mempool also triggers removal of the entry's Ref from txgraph. */614void removeUnchecked(txiter entry, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs);615public:616/*617* CTxMemPool::ChangeSet:618*619* This class is used for all mempool additions and associated removals (eg620* due to rbf). Removals that don't need to be evaluated for acceptance,621* such as removing transactions that appear in a block, or due to reorg,622* or removals related to mempool limiting or expiry do not need to use623* this.624*625* Callers can interleave calls to StageAddition()/StageRemoval(), and626* removals may be invoked in any order, but additions must be done in a627* topological order in the case of transaction packages (ie, parents must628* be added before children).629*630* CalculateChunksForRBF() can be used to calculate the feerate diagram of631* the proposed set of new transactions and compare with the existing632* mempool.633*634* CalculateMemPoolAncestors() calculates the in-mempool (not including635* what is in the change set itself) ancestors of a given transaction.636*637* Apply() will apply the removals and additions that are staged into the638* mempool.639*640* Only one changeset may exist at a time. While a changeset is641* outstanding, no removals or additions may be made directly to the642* mempool.643*/644class ChangeSet {645public:646explicit ChangeSet(CTxMemPool* pool) : m_pool(pool) { m_pool->m_txgraph->StartStaging(); }647~ChangeSet() EXCLUSIVE_LOCKS_REQUIRED(m_pool->cs) {648AssertLockHeld(m_pool->cs);649if (m_pool->m_txgraph->HaveStaging()) {650m_pool->m_txgraph->AbortStaging();651}652m_pool->m_have_changeset = false;653}655ChangeSet(const ChangeSet&) = delete;656ChangeSet& operator=(const ChangeSet&) = delete;658using TxHandle = CTxMemPool::txiter;660TxHandle 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);662void StageRemoval(CTxMemPool::txiter it);664const CTxMemPool::setEntries& GetRemovals() const { return m_to_remove; }666/** Check if any cluster limits are exceeded. Returns true if pass, false if fail. */667bool CheckMemPoolPolicyLimits();669CTxMemPool::setEntries CalculateMemPoolAncestors(TxHandle tx)670{671// Look up transaction in our cache first672auto it = m_ancestors.find(tx);673if (it != m_ancestors.end()) return it->second;675// If not found, try to have the mempool calculate it, and cache676// for later.677LOCK(m_pool->cs);678auto ret = m_pool->CalculateMemPoolAncestors(*tx);679m_ancestors.try_emplace(tx, ret);680return ret;681}683std::vector<CTransactionRef> GetAddedTxns() const {684std::vector<CTransactionRef> ret;685ret.reserve(m_entry_vec.size());686for (const auto& entry : m_entry_vec) {687ret.emplace_back(entry->GetSharedTx());688}689return ret;690}692/**693* Calculate the sorted chunks for the old and new mempool relating to the694* clusters that would be affected by a potential replacement transaction.695*696* @return old and new diagram pair respectively, or an error string if the conflicts don't match a calculable topology697*/698util::Result<std::pair<std::vector<FeeFrac>, std::vector<FeeFrac>>> CalculateChunksForRBF();700size_t GetTxCount() const { return m_entry_vec.size(); }701const CTransaction& GetAddedTxn(size_t index) const { return m_entry_vec.at(index)->GetTx(); }703void Apply() EXCLUSIVE_LOCKS_REQUIRED(cs_main);705private:706void ProcessDependencies();708CTxMemPool* m_pool;709CTxMemPool::indexed_transaction_set m_to_add;710std::vector<CTxMemPool::txiter> m_entry_vec; // track the added transactions' insertion order711// map from the m_to_add index to the ancestors for the transaction712std::map<CTxMemPool::txiter, CTxMemPool::setEntries, CompareIteratorByHash> m_ancestors;713CTxMemPool::setEntries m_to_remove;714bool m_dependencies_processed{false};716friend class CTxMemPool;717};719std::unique_ptr<ChangeSet> GetChangeSet() EXCLUSIVE_LOCKS_REQUIRED(cs) {720Assume(!m_have_changeset);721m_have_changeset = true;722return std::make_unique<ChangeSet>(this);723}725bool m_have_changeset GUARDED_BY(cs){false};727friend class CTxMemPool::ChangeSet;729private:730// Apply the given changeset to the mempool, by removing transactions in731// the to_remove set and adding transactions in the to_add set.732void Apply(CTxMemPool::ChangeSet* changeset) EXCLUSIVE_LOCKS_REQUIRED(cs);734// addNewTransaction must update state for all ancestors of a given transaction,735// to track size/count of descendant transactions. First version of736// addNewTransaction can be used to have it call CalculateMemPoolAncestors(), and737// then invoke the second version.738// Note that addNewTransaction is ONLY called (via Apply()) from ATMP739// outside of tests and any other callers may break wallet's in-mempool740// tracking (due to lack of CValidationInterface::TransactionAddedToMempool741// callbacks).742void addNewTransaction(CTxMemPool::txiter it) EXCLUSIVE_LOCKS_REQUIRED(cs);743public:744void StartBlockBuilding() const EXCLUSIVE_LOCKS_REQUIRED(cs) { assert(!m_builder); m_builder = m_txgraph->GetBlockBuilder(); }745FeePerWeight GetBlockBuilderChunk(std::vector<CTxMemPoolEntry::CTxMemPoolEntryRef>& entries) const EXCLUSIVE_LOCKS_REQUIRED(cs)746{747if (!m_builder) { return {}; }749auto res = m_builder->GetCurrentChunk();750if (!res) { return {}; }
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.