Inside Bitcoin
Opening the selected file…
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.
752// RBF-related members753/** Whether the transaction(s) would replace any mempool transactions and/or evict any siblings.754* If so, RBF rules apply. */755bool m_rbf{false};756/** Mempool transactions that were replaced. */757std::list<CTransactionRef> m_replaced_transactions;758/* Changeset representing adding transactions and removing their conflicts. */759std::unique_ptr<CTxMemPool::ChangeSet> m_changeset;761/** Total modified fees of mempool transactions being replaced. */762CAmount m_conflicting_fees{0};763/** Total size (in virtual bytes) of mempool transactions being replaced. */764size_t m_conflicting_size{0};765};767struct SubPackageState m_subpackage;769/** Re-set sub-package state to not leak between evaluations */770void ClearSubPackageState() EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs)771{772m_subpackage = SubPackageState{};774// And clean coins while at it775CleanupTemporaryCoins();776}777};779bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)780{781AssertLockHeld(cs_main);782AssertLockHeld(m_pool.cs);783const CTransactionRef& ptx = ws.m_ptx;784const CTransaction& tx = *ws.m_ptx;785const Txid& hash = ws.m_hash;787// Copy/alias what we need out of args788const int64_t nAcceptTime = args.m_accept_time;789const bool bypass_limits = args.m_bypass_limits;790std::vector<COutPoint>& coins_to_uncache = args.m_coins_to_uncache;792// Alias what we need out of ws793TxValidationState& state = ws.m_state;795if (!CheckTransaction(tx, state)) {796return false; // state filled in by CheckTransaction797}799// Coinbase is only valid in a block, not as a loose transaction800if (tx.IsCoinBase())801return state.Invalid(TxValidationResult::TX_CONSENSUS, "coinbase");803// Rather not work on nonstandard transactions (unless -testnet/-regtest)804std::string reason;805if (m_pool.m_opts.require_standard && !IsStandardTx(tx, m_pool.m_opts.max_datacarrier_bytes, m_pool.m_opts.permit_bare_multisig, m_pool.m_opts.dust_relay_feerate, reason)) {806return state.Invalid(TxValidationResult::TX_NOT_STANDARD, reason);807}809// Transactions smaller than 65 non-witness bytes are not relayed to mitigate CVE-2017-12842.810if (::GetSerializeSize(TX_NO_WITNESS(tx)) < MIN_STANDARD_TX_NONWITNESS_SIZE)811return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "tx-size-small");813// Only accept nLockTime-using transactions that can be mined in the next814// block; we don't want our mempool filled up with transactions that can't815// be mined yet.816if (!CheckFinalTxAtTip(*Assert(m_active_chainstate.m_chain.Tip()), tx)) {817return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-final");818}820if (m_pool.exists(tx.GetWitnessHash())) {821// Exact transaction already exists in the mempool.822return state.Invalid(TxValidationResult::TX_CONFLICT, "txn-already-in-mempool");823} else if (m_pool.exists(tx.GetHash())) {824// Transaction with the same non-witness data but different witness (same txid, different825// wtxid) already exists in the mempool.826return state.Invalid(TxValidationResult::TX_CONFLICT, "txn-same-nonwitness-data-in-mempool");827}829// Check for conflicts with in-memory transactions830for (const CTxIn &txin : tx.vin)831{832const CTransaction* ptxConflicting = m_pool.GetConflictTx(txin.prevout);833if (ptxConflicting) {834if (!args.m_allow_replacement) {835// Transaction conflicts with a mempool tx, but we're not allowing replacements in this context.836return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "bip125-replacement-disallowed");837}838ws.m_conflicts.insert(ptxConflicting->GetHash());839}840}842m_view.SetBackend(m_viewmempool);844const CCoinsViewCache& coins_cache = m_active_chainstate.CoinsTip();845// do all inputs exist?846for (const CTxIn& txin : tx.vin) {847if (!coins_cache.HaveCoinInCache(txin.prevout)) {848coins_to_uncache.push_back(txin.prevout);849}851// Note: this call may add txin.prevout to the coins cache852// (coins_cache.cacheCoins) by way of FetchCoin(). It should be removed853// later (via coins_to_uncache) if this tx turns out to be invalid.854if (!m_view.HaveCoin(txin.prevout)) {855// Are inputs missing because we already have the tx?856for (size_t out = 0; out < tx.vout.size(); out++) {857// Optimistically just do efficient check of cache for outputs858if (coins_cache.HaveCoinInCache(COutPoint(hash, out))) {859return state.Invalid(TxValidationResult::TX_CONFLICT, "txn-already-known");860}861}862// Otherwise assume this might be an orphan tx for which we just haven't seen parents yet863return state.Invalid(TxValidationResult::TX_MISSING_INPUTS, "bad-txns-inputs-missingorspent");864}865}867// This is const, but calls into `CCoinsViewCache::GetBestBlock()` to refresh868// the cached best block through `m_viewmempool` after caching inputs.869(void)m_view.GetBestBlock();871// All required inputs are cached now, so switch m_view to the empty backend.872// This keeps already-fetched cache entries for later checks and prevents new873// backend lookups (which would avoid coins_to_uncache tracking).874m_view.SetBackend(CoinsViewEmpty::Get());876assert(m_active_chainstate.m_blockman.LookupBlockIndex(m_view.GetBestBlock()) == m_active_chainstate.m_chain.Tip());878// Only accept BIP68 sequence locked transactions that can be mined in the next879// block; we don't want our mempool filled up with transactions that can't880// be mined yet.881// Pass in m_view which has all of the relevant inputs cached. Note that, since m_view's882// backend was removed, it no longer pulls coins from the mempool.883const std::optional<LockPoints> lock_points{CalculateLockPointsAtTip(m_active_chainstate.m_chain.Tip(), m_view, tx)};884if (!lock_points.has_value() || !CheckSequenceLocksAtTip(m_active_chainstate.m_chain.Tip(), *lock_points)) {885return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-BIP68-final");886}888// The mempool holds txs for the next block, so pass height+1 to CheckTxInputs889if (!Consensus::CheckTxInputs(tx, state, m_view, m_active_chainstate.m_chain.Height() + 1, ws.m_base_fees)) {890return false; // state filled in by CheckTxInputs891}893if (m_pool.m_opts.require_standard) {894state = ValidateInputsStandardness(tx, m_view);895if (state.IsInvalid()) {896return false;897}898}900// Check for non-standard witnesses.901if (tx.HasWitness() && m_pool.m_opts.require_standard && !IsWitnessStandard(tx, m_view)) {902return state.Invalid(TxValidationResult::TX_WITNESS_MUTATED, "bad-witness-nonstandard");903}905int64_t nSigOpsCost = GetTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS);907// Keep track of transactions that spend a coinbase, which we re-scan908// during reorgs to ensure COINBASE_MATURITY is still met.909bool fSpendsCoinbase = false;910for (const CTxIn &txin : tx.vin) {911const Coin &coin = m_view.AccessCoin(txin.prevout);912if (coin.IsCoinBase()) {913fSpendsCoinbase = true;914break;915}916}918// Set entry_sequence to 0 when bypass_limits is used; this allows txs from a block919// reorg to be marked earlier than any child txs that were already in the mempool.920const uint64_t entry_sequence = bypass_limits ? 0 : m_pool.GetSequence();921if (!m_subpackage.m_changeset) {922m_subpackage.m_changeset = m_pool.GetChangeSet();923}924ws.m_tx_handle = m_subpackage.m_changeset->StageAddition(ptx, ws.m_base_fees, nAcceptTime, m_active_chainstate.m_chain.Height(), entry_sequence, fSpendsCoinbase, nSigOpsCost, lock_points.value());926// ws.m_modified_fees includes any fee deltas from PrioritiseTransaction927ws.m_modified_fees = ws.m_tx_handle->GetModifiedFee();929ws.m_vsize = ws.m_tx_handle->GetTxSize();931// Enforces 0-fee for dust transactions, no incentive to be mined alone932if (m_pool.m_opts.require_standard) {933if (!PreCheckEphemeralTx(*ptx, m_pool.m_opts.dust_relay_feerate, ws.m_base_fees, ws.m_modified_fees, state)) {934return false; // state filled in by PreCheckEphemeralTx935}936}938if (nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST)939return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "bad-txns-too-many-sigops",940strprintf("%d", nSigOpsCost));942// No individual transactions are allowed below the mempool min feerate except from disconnected943// blocks and transactions in a package. Package transactions will be checked using package944// feerate later.945if (!bypass_limits && !args.m_package_feerates && !CheckFeeRate(ws.m_vsize, ws.m_modified_fees, state)) return false;947ws.m_iters_conflicting = m_pool.GetIterSet(ws.m_conflicts);949ws.m_parents = m_pool.GetParents(*ws.m_tx_handle);951if (!args.m_bypass_limits) {952// Perform the TRUC checks, using the in-mempool parents.953if (const auto err{SingleTRUCChecks(m_pool, ws.m_ptx, ws.m_parents, ws.m_conflicts, ws.m_vsize)}) {954// Single transaction contexts only.955if (args.m_allow_sibling_eviction && err->second != nullptr) {956// We should only be considering where replacement is considered valid as well.957Assume(args.m_allow_replacement);958// Potential sibling eviction. Add the sibling to our list of mempool conflicts to be959// included in RBF checks.960ws.m_conflicts.insert(err->second->GetHash());961// Adding the sibling to m_iters_conflicting here means that it doesn't count towards962// RBF Carve Out above. This is correct, since removing to-be-replaced transactions from963// the descendant count is done separately in SingleTRUCChecks for TRUC transactions.964ws.m_iters_conflicting.insert(m_pool.GetIter(err->second->GetHash()).value());965ws.m_sibling_eviction = true;966// The sibling will be treated as part of the to-be-replaced set in ReplacementChecks.967// Note that we are not checking whether it opts in to replaceability via BIP125 or TRUC968// (which is normally done in PreChecks). However, the only way a TRUC transaction can969// have a non-TRUC and non-BIP125 descendant is due to a reorg.970} else {971return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "TRUC-violation", err->first);972}973}974}976// We want to detect conflicts in any tx in a package to trigger package RBF logic977m_subpackage.m_rbf |= !ws.m_conflicts.empty();978return true;979}981bool MemPoolAccept::ReplacementChecks(Workspace& ws)982{983AssertLockHeld(cs_main);984AssertLockHeld(m_pool.cs);986const CTransaction& tx = *ws.m_ptx;987const Txid& hash = ws.m_hash;988TxValidationState& state = ws.m_state;990CTxMemPool::setEntries all_conflicts;992// Calculate all conflicting entries and enforce Rule #5.993if (const auto err_string{GetEntriesForConflicts(tx, m_pool, ws.m_iters_conflicting, all_conflicts)}) {994return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,995strprintf("too many potential replacements%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);996}998// Check if it's economically rational to mine this transaction rather than the ones it999// replaces and pays for its own relay fees. Enforce Rules #3 and #4.1000for (CTxMemPool::txiter it : all_conflicts) {