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.
251// signifies no relative lock time.252return LockPoints{min_height, min_time, Assert(tip->GetAncestor(max_input_height))};253}255bool CheckSequenceLocksAtTip(CBlockIndex* tip,256const LockPoints& lock_points)257{258assert(tip != nullptr);260CBlockIndex index;261index.pprev = tip;262// CheckSequenceLocksAtTip() uses active_chainstate.m_chain.Height()+1 to evaluate263// height based locks because when SequenceLocks() is called within264// ConnectBlock(), the height of the block *being*265// evaluated is what is used.266// Thus if we want to know if a transaction can be part of the267// *next* block, we need to use one more than active_chainstate.m_chain.Height()268index.nHeight = tip->nHeight + 1;270return EvaluateSequenceLocks(index, {lock_points.height, lock_points.time});271}273static void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache)274EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs)275{276AssertLockHeld(::cs_main);277AssertLockHeld(pool.cs);278int expired = pool.Expire(GetTime<std::chrono::seconds>() - pool.m_opts.expiry);279if (expired != 0) {280LogDebug(BCLog::MEMPOOL, "Expired %i transactions from the memory pool\n", expired);281}283std::vector<COutPoint> vNoSpendsRemaining;284pool.TrimToSize(pool.m_opts.max_size_bytes, &vNoSpendsRemaining);285for (const COutPoint& removed : vNoSpendsRemaining)286coins_cache.Uncache(removed);287}289static bool IsCurrentForFeeEstimation(Chainstate& active_chainstate) EXCLUSIVE_LOCKS_REQUIRED(cs_main)290{291AssertLockHeld(cs_main);292if (active_chainstate.m_chainman.IsInitialBlockDownload()) {293return false;294}295if (active_chainstate.m_chain.Tip()->GetBlockTime() < count_seconds(GetTime<std::chrono::seconds>() - MAX_FEE_ESTIMATION_TIP_AGE))296return false;297if (active_chainstate.m_chain.Height() < active_chainstate.m_chainman.m_best_header->nHeight - 1) {298return false;299}300return true;301}303void Chainstate::MaybeUpdateMempoolForReorg(304DisconnectedBlockTransactions& disconnectpool,305bool fAddToMempool)306{307if (!m_mempool) return;309AssertLockHeld(cs_main);310AssertLockHeld(m_mempool->cs);311std::vector<Txid> vHashUpdate;312{313// disconnectpool is ordered so that the front is the most recently-confirmed314// transaction (the last tx of the block at the tip) in the disconnected chain.315// Iterate disconnectpool in reverse, so that we add transactions316// back to the mempool starting with the earliest transaction that had317// been previously seen in a block.318const auto queuedTx = disconnectpool.take();319auto it = queuedTx.rbegin();320while (it != queuedTx.rend()) {321// ignore validation errors in resurrected transactions322if (!fAddToMempool || (*it)->IsCoinBase() ||323AcceptToMemoryPool(*this, *it, GetTime(),324/*bypass_limits=*/true, /*test_accept=*/false).m_result_type !=325MempoolAcceptResult::ResultType::VALID) {326// If the transaction doesn't make it in to the mempool, remove any327// transactions that depend on it (which would now be orphans).328m_mempool->removeRecursive(**it, MemPoolRemovalReason::REORG);329} else if (m_mempool->exists((*it)->GetHash())) {330vHashUpdate.push_back((*it)->GetHash());331}332++it;333}334}336// AcceptToMemoryPool/addNewTransaction all assume that new mempool entries have337// no in-mempool children, which is generally not true when adding338// previously-confirmed transactions back to the mempool.339// UpdateTransactionsFromBlock finds descendants of any transactions in340// the disconnectpool that were added back and cleans up the mempool state.341m_mempool->UpdateTransactionsFromBlock(vHashUpdate);343// Predicate to use for filtering transactions in removeForReorg.344// Checks whether the transaction is still final and, if it spends a coinbase output, mature.345// Also updates valid entries' cached LockPoints if needed.346// If false, the tx is still valid and its lockpoints are updated.347// If true, the tx would be invalid in the next block; remove this entry and all of its descendants.348// Note that TRUC rules are not applied here, so reorgs may cause violations of TRUC inheritance or349// topology restrictions.350const auto filter_final_and_mature = [&](CTxMemPool::txiter it)351EXCLUSIVE_LOCKS_REQUIRED(m_mempool->cs, ::cs_main) {352AssertLockHeld(m_mempool->cs);353AssertLockHeld(::cs_main);354const CTransaction& tx = it->GetTx();356// The transaction must be final.357if (!CheckFinalTxAtTip(*Assert(m_chain.Tip()), tx)) return true;359const LockPoints& lp = it->GetLockPoints();360// CheckSequenceLocksAtTip checks if the transaction will be final in the next block to be361// created on top of the new chain.362if (TestLockPointValidity(m_chain, lp)) {363if (!CheckSequenceLocksAtTip(m_chain.Tip(), lp)) {364return true;365}366} else {367const CCoinsViewMemPool view_mempool{&CoinsTip(), *m_mempool};368const std::optional<LockPoints> new_lock_points{CalculateLockPointsAtTip(m_chain.Tip(), view_mempool, tx)};369if (new_lock_points.has_value() && CheckSequenceLocksAtTip(m_chain.Tip(), *new_lock_points)) {370// Now update the mempool entry lockpoints as well.371it->UpdateLockPoints(*new_lock_points);372} else {373return true;374}375}377// If the transaction spends any coinbase outputs, it must be mature.378if (it->GetSpendsCoinbase()) {379for (const CTxIn& txin : tx.vin) {380if (m_mempool->exists(txin.prevout.hash)) continue;381const Coin& coin{CoinsTip().AccessCoin(txin.prevout)};382assert(!coin.IsSpent());383const auto mempool_spend_height{m_chain.Tip()->nHeight + 1};384if (coin.IsCoinBase() && mempool_spend_height - coin.nHeight < COINBASE_MATURITY) {385return true;386}387}388}389// Transaction is still valid and cached LockPoints are updated.390return false;391};393// We also need to remove any now-immature transactions394m_mempool->removeForReorg(m_chain, filter_final_and_mature);395// Re-limit mempool size, in case we added any transactions396LimitMempoolSize(*m_mempool, this->CoinsTip());397}399/**400* Checks to avoid mempool polluting consensus critical paths since cached401* signature and script validity results will be reused if we validate this402* transaction again during block validation.403* */404static bool CheckInputsFromMempoolAndCache(const CTransaction& tx, TxValidationState& state,405const CCoinsViewCache& view, const CTxMemPool& pool,406script_verify_flags flags, PrecomputedTransactionData& txdata, CCoinsViewCache& coins_tip,407ValidationCache& validation_cache)408EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs)409{410AssertLockHeld(cs_main);411AssertLockHeld(pool.cs);413assert(!tx.IsCoinBase());414for (const CTxIn& txin : tx.vin) {415const Coin& coin = view.AccessCoin(txin.prevout);417// This coin was checked in PreChecks and MemPoolAccept418// has been holding cs_main since then.419Assume(!coin.IsSpent());420if (coin.IsSpent()) return false;422// If the Coin is available, there are 2 possibilities:423// it is available in our current ChainstateActive UTXO set,424// or it's a UTXO provided by a transaction in our mempool.425// Ensure the scriptPubKeys in Coins from CoinsView are correct.426const CTransactionRef& txFrom = pool.get(txin.prevout.hash);427if (txFrom) {428assert(txFrom->GetHash() == txin.prevout.hash);429assert(txFrom->vout.size() > txin.prevout.n);430assert(txFrom->vout[txin.prevout.n] == coin.out);431} else {432const Coin& coinFromUTXOSet = coins_tip.AccessCoin(txin.prevout);433assert(!coinFromUTXOSet.IsSpent());434assert(coinFromUTXOSet.out == coin.out);435}436}438// Call CheckInputScripts() to cache signature and script validity against current tip consensus rules.439return CheckInputScripts(tx, state, view, flags, /* cacheSigStore= */ true, /* cacheFullScriptStore= */ true, txdata, validation_cache);440}442namespace {444class MemPoolAccept445{446public:447explicit MemPoolAccept(CTxMemPool& mempool, Chainstate& active_chainstate) :448m_pool(mempool),449m_view(&CoinsViewEmpty::Get()),450m_viewmempool(&active_chainstate.CoinsTip(), m_pool),451m_active_chainstate(active_chainstate)452{453}455// We put the arguments we're handed into a struct, so we can pass them456// around easier.457struct ATMPArgs {458const int64_t m_accept_time;459const bool m_bypass_limits;460/*461* Return any outpoints which were not previously present in the coins462* cache, but were added as a result of validating the tx for mempool463* acceptance. This allows the caller to optionally remove the cache464* additions if the associated transaction ends up being rejected by465* the mempool.466*/467std::vector<COutPoint>& m_coins_to_uncache;468/** When true, the transaction or package will not be submitted to the mempool. */469const bool m_test_accept;470/** Whether we allow transactions to replace mempool transactions. If false,471* any transaction spending the same inputs as a transaction in the mempool is considered472* a conflict. */473const bool m_allow_replacement;474/** When true, allow sibling eviction. This only occurs in single transaction package settings. */475const bool m_allow_sibling_eviction;476/** Used to skip the LimitMempoolSize() call within AcceptSingleTransaction(). This should be used when multiple477* AcceptSubPackage calls are expected and the mempool will be trimmed at the end of AcceptPackage(). */478const bool m_package_submission;479/** When true, use package feerates instead of individual transaction feerates for fee-based480* policies such as mempool min fee and min relay fee.481*/482const bool m_package_feerates;483/** Used for local submission of transactions to catch "absurd" fees484* due to fee miscalculation by wallets. std:nullopt implies unset, allowing any feerates.485* Any individual transaction failing this check causes immediate failure.486*/487const std::optional<CFeeRate> m_client_maxfeerate;489/** Parameters for single transaction mempool validation. */490static ATMPArgs SingleAccept(int64_t accept_time,491bool bypass_limits, std::vector<COutPoint>& coins_to_uncache,492bool test_accept) {493return ATMPArgs{/*accept_time=*/ accept_time,494/*bypass_limits=*/ bypass_limits,495/*coins_to_uncache=*/ coins_to_uncache,496/*test_accept=*/ test_accept,497/*allow_replacement=*/ true,498/*allow_sibling_eviction=*/ true,499/*package_submission=*/ false,500/*package_feerates=*/ false,