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.
1251// ConsensusScriptChecks to make the outputs available for subsequent transactions.1252for (Workspace& ws : workspaces) {1253if (!ConsensusScriptChecks(ws)) {1254results.emplace(ws.m_ptx->GetWitnessHash(), MempoolAcceptResult::Failure(ws.m_state));1255// Since PolicyScriptChecks() passed, this should never fail.1256Assume(false);1257all_submitted = false;1258package_state.Invalid(PackageValidationResult::PCKG_MEMPOOL_ERROR,1259strprintf("BUG! PolicyScriptChecks succeeded but ConsensusScriptChecks failed: %s",1260ws.m_ptx->GetHash().ToString()));1261}1262// Remove first failing tx and all subsequent in package1263if (!all_submitted) {1264if (!m_subpackage.m_changeset) m_subpackage.m_changeset = m_pool.GetChangeSet();1265m_subpackage.m_changeset->StageRemoval(m_pool.GetIter(ws.m_ptx->GetHash()).value());1266}1267}1268if (!all_submitted) {1269Assume(m_subpackage.m_changeset);1270// This code should be unreachable; it's here as belt-and-suspenders1271// to try to ensure we have no consensus-invalid transactions in the1272// mempool.1273m_subpackage.m_changeset->Apply();1274m_subpackage.m_changeset.reset();1275return false;1276}1278std::vector<Wtxid> all_package_wtxids;1279all_package_wtxids.reserve(workspaces.size());1280std::transform(workspaces.cbegin(), workspaces.cend(), std::back_inserter(all_package_wtxids),1281[](const auto& ws) { return ws.m_ptx->GetWitnessHash(); });1283if (!m_subpackage.m_replaced_transactions.empty()) {1284LogDebug(BCLog::MEMPOOL, "replaced %u mempool transactions with %u new one(s) for %s additional fees, %d delta bytes\n",1285m_subpackage.m_replaced_transactions.size(), workspaces.size(),1286m_subpackage.m_total_modified_fees - m_subpackage.m_conflicting_fees,1287m_subpackage.m_total_vsize - static_cast<int>(m_subpackage.m_conflicting_size));1288}1290// Add successful results. The returned results may change later if LimitMempoolSize() evicts them.1291for (Workspace& ws : workspaces) {1292auto iter = m_pool.GetIter(ws.m_ptx->GetHash());1293Assume(iter.has_value());1294const auto effective_feerate = args.m_package_feerates ? ws.m_package_feerate :1295CFeeRate{ws.m_modified_fees, static_cast<int32_t>(ws.m_vsize)};1296const auto effective_feerate_wtxids = args.m_package_feerates ? all_package_wtxids :1297std::vector<Wtxid>{ws.m_ptx->GetWitnessHash()};1298results.emplace(ws.m_ptx->GetWitnessHash(),1299MempoolAcceptResult::Success(std::move(m_subpackage.m_replaced_transactions), ws.m_vsize,1300ws.m_base_fees, effective_feerate, effective_feerate_wtxids));1301if (!m_pool.m_opts.signals) continue;1302const CTransaction& tx = *ws.m_ptx;1303const auto tx_info = NewMempoolTransactionInfo(ws.m_ptx, ws.m_base_fees,1304ws.m_vsize, (*iter)->GetHeight(),1305args.m_bypass_limits, args.m_package_submission,1306IsCurrentForFeeEstimation(m_active_chainstate),1307m_pool.HasNoInputsOf(tx));1308m_pool.m_opts.signals->TransactionAddedToMempool(tx_info, m_pool.GetAndIncrementSequence());1309}1310return all_submitted;1311}1313MempoolAcceptResult MemPoolAccept::AcceptSingleTransactionInternal(const CTransactionRef& ptx, ATMPArgs& args)1314{1315AssertLockHeld(cs_main);1316AssertLockHeld(m_pool.cs);1318Workspace ws(ptx);1319const std::vector<Wtxid> single_wtxid{ws.m_ptx->GetWitnessHash()};1321if (!PreChecks(args, ws)) {1322if (ws.m_state.GetResult() == TxValidationResult::TX_RECONSIDERABLE) {1323// Failed for fee reasons. Provide the effective feerate and which tx was included.1324return MempoolAcceptResult::FeeFailure(ws.m_state, CFeeRate(ws.m_modified_fees, ws.m_vsize), single_wtxid);1325}1326return MempoolAcceptResult::Failure(ws.m_state);1327}1329if (m_subpackage.m_rbf && !ReplacementChecks(ws)) {1330if (ws.m_state.GetResult() == TxValidationResult::TX_RECONSIDERABLE) {1331// Failed for incentives-based fee reasons. Provide the effective feerate and which tx was included.1332return MempoolAcceptResult::FeeFailure(ws.m_state, CFeeRate(ws.m_modified_fees, ws.m_vsize), single_wtxid);1333}1334return MempoolAcceptResult::Failure(ws.m_state);1335}1337// Check if the transaction would exceed the cluster size limit.1338if (!m_subpackage.m_changeset->CheckMemPoolPolicyLimits()) {1339ws.m_state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "too-large-cluster", "");1340return MempoolAcceptResult::Failure(ws.m_state);1341}1343// Now that we've verified the cluster limit is respected, we can perform1344// calculations involving the full ancestors of the tx.1345if (ws.m_conflicts.size()) {1346auto ancestors = m_subpackage.m_changeset->CalculateMemPoolAncestors(ws.m_tx_handle);1348// A transaction that spends outputs that would be replaced by it is invalid. Now1349// that we have the set of all ancestors we can detect this1350// pathological case by making sure ws.m_conflicts and this tx's ancestors don't1351// intersect.1352if (const auto err_string{EntriesAndTxidsDisjoint(ancestors, ws.m_conflicts, ptx->GetHash())}) {1353// We classify this as a consensus error because a transaction depending on something it1354// conflicts with would be inconsistent.1355ws.m_state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-spends-conflicting-tx", *err_string);1356return MempoolAcceptResult::Failure(ws.m_state);1357}1358}1360m_subpackage.m_total_vsize = ws.m_vsize;1361m_subpackage.m_total_modified_fees = ws.m_modified_fees;1363// Individual modified feerate exceeded caller-defined max; abort1364if (args.m_client_maxfeerate && CFeeRate(ws.m_modified_fees, ws.m_vsize) > args.m_client_maxfeerate.value()) {1365ws.m_state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "max feerate exceeded", "");1366return MempoolAcceptResult::Failure(ws.m_state);1367}1369if (!args.m_bypass_limits && m_pool.m_opts.require_standard) {1370Wtxid dummy_wtxid;1371if (!CheckEphemeralSpends(/*package=*/{ptx}, m_pool.m_opts.dust_relay_feerate, m_pool, ws.m_state, dummy_wtxid)) {1372return MempoolAcceptResult::Failure(ws.m_state);1373}1374}1376// Perform the inexpensive checks first and avoid hashing and signature verification unless1377// those checks pass, to mitigate CPU exhaustion denial-of-service attacks.1378if (!PolicyScriptChecks(ws)) return MempoolAcceptResult::Failure(ws.m_state);1380if (!ConsensusScriptChecks(ws)) return MempoolAcceptResult::Failure(ws.m_state);1382const CFeeRate effective_feerate{ws.m_modified_fees, static_cast<int32_t>(ws.m_vsize)};1383// Tx was accepted, but not added1384if (args.m_test_accept) {1385return MempoolAcceptResult::Success(std::move(m_subpackage.m_replaced_transactions), ws.m_vsize,1386ws.m_base_fees, effective_feerate, single_wtxid);1387}1389FinalizeSubpackage(args);1391// Limit the mempool, if appropriate.1392if (!args.m_package_submission && !args.m_bypass_limits) {1393LimitMempoolSize(m_pool, m_active_chainstate.CoinsTip());1394// If mempool contents change, then the m_view cache is dirty. Given this isn't a package1395// submission, we won't be using the cache anymore, but clear it anyway for clarity.1396CleanupTemporaryCoins();1398if (!m_pool.exists(ws.m_hash)) {1399// The tx no longer meets our (new) mempool minimum feerate but could be reconsidered in a package.1400ws.m_state.Invalid(TxValidationResult::TX_RECONSIDERABLE, "mempool full");1401return MempoolAcceptResult::FeeFailure(ws.m_state, CFeeRate(ws.m_modified_fees, ws.m_vsize), {ws.m_ptx->GetWitnessHash()});1402}1403}1405if (m_pool.m_opts.signals) {1406const CTransaction& tx = *ws.m_ptx;1407auto iter = m_pool.GetIter(tx.GetHash());1408Assume(iter.has_value());1409const auto tx_info = NewMempoolTransactionInfo(ws.m_ptx, ws.m_base_fees,1410ws.m_vsize, (*iter)->GetHeight(),1411args.m_bypass_limits, args.m_package_submission,1412IsCurrentForFeeEstimation(m_active_chainstate),1413m_pool.HasNoInputsOf(tx));1414m_pool.m_opts.signals->TransactionAddedToMempool(tx_info, m_pool.GetAndIncrementSequence());1415}1417if (!m_subpackage.m_replaced_transactions.empty()) {1418LogDebug(BCLog::MEMPOOL, "replaced %u mempool transactions with 1 new transaction for %s additional fees, %d delta bytes\n",1419m_subpackage.m_replaced_transactions.size(),1420ws.m_modified_fees - m_subpackage.m_conflicting_fees,1421ws.m_vsize - static_cast<int>(m_subpackage.m_conflicting_size));1422}1424return MempoolAcceptResult::Success(std::move(m_subpackage.m_replaced_transactions), ws.m_vsize, ws.m_base_fees,1425effective_feerate, single_wtxid);1426}1428PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactionsInternal(const std::vector<CTransactionRef>& txns, ATMPArgs& args)1429{1430AssertLockHeld(cs_main);1431AssertLockHeld(m_pool.cs);1433// These context-free package limits can be done before taking the mempool lock.1434PackageValidationState package_state;1435if (!IsWellFormedPackage(txns, package_state)) return PackageMempoolAcceptResult(package_state, {});1437std::vector<Workspace> workspaces{};1438workspaces.reserve(txns.size());1439std::transform(txns.cbegin(), txns.cend(), std::back_inserter(workspaces),1440[](const auto& tx) { return Workspace(tx); });1441std::map<Wtxid, MempoolAcceptResult> results;1443// Do all PreChecks first and fail fast to avoid running expensive script checks when unnecessary.1444for (Workspace& ws : workspaces) {1445if (!PreChecks(args, ws)) {1446package_state.Invalid(PackageValidationResult::PCKG_TX, "transaction failed");1447// Exit early to avoid doing pointless work. Update the failed tx result; the rest are unfinished.1448results.emplace(ws.m_ptx->GetWitnessHash(), MempoolAcceptResult::Failure(ws.m_state));1449return PackageMempoolAcceptResult(package_state, std::move(results));1450}1452// Individual modified feerate exceeded caller-defined max; abort1453// N.B. this doesn't take into account CPFPs. Chunk-aware validation may be more robust.1454if (args.m_client_maxfeerate && CFeeRate(ws.m_modified_fees, ws.m_vsize) > args.m_client_maxfeerate.value()) {1455// Need to set failure here both individually and at package level1456ws.m_state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "max feerate exceeded", "");1457package_state.Invalid(PackageValidationResult::PCKG_TX, "transaction failed");1458// Exit early to avoid doing pointless work. Update the failed tx result; the rest are unfinished.1459results.emplace(ws.m_ptx->GetWitnessHash(), MempoolAcceptResult::Failure(ws.m_state));1460return PackageMempoolAcceptResult(package_state, std::move(results));1461}1463// Make the coins created by this transaction available for subsequent transactions in the1464// package to spend. If there are no conflicts within the package, no transaction can spend a coin1465// needed by another transaction in the package. We also need to make sure that no package1466// tx replaces (or replaces the ancestor of) the parent of another package tx. As long as we1467// check these two things, we don't need to track the coins spent.1468// If a package tx conflicts with a mempool tx, PackageRBFChecks() ensures later that any package RBF attempt1469// has *no* in-mempool ancestors, so we don't have to worry about subsequent transactions in1470// same package spending the same in-mempool outpoints. This needs to be revisited for general1471// package RBF.1472m_viewmempool.PackageAddTransaction(ws.m_ptx);1473}1475// At this point we have all in-mempool parents, and we know every transaction's vsize.1476// Run the TRUC checks on the package.1477for (Workspace& ws : workspaces) {1478if (auto err{PackageTRUCChecks(m_pool, ws.m_ptx, ws.m_vsize, txns, ws.m_parents)}) {1479package_state.Invalid(PackageValidationResult::PCKG_POLICY, "TRUC-violation", err.value());1480return PackageMempoolAcceptResult(package_state, {});1481}1482}1484// Transactions must meet two minimum feerates: the mempool minimum fee and min relay fee.1485// For transactions consisting of exactly one child and its parents, it suffices to use the1486// package feerate (total modified fees / total virtual size) to check this requirement.1487// Note that this is an aggregate feerate; this function has not checked that there are transactions1488// too low feerate to pay for themselves, or that the child transactions are higher feerate than1489// their parents. Using aggregate feerate may allow "parents pay for child" behavior and permit1490// a child that is below mempool minimum feerate. To avoid these behaviors, callers of1491// AcceptMultipleTransactions need to restrict txns topology (e.g. to ancestor sets) and check1492// the feerates of individuals and subsets.1493m_subpackage.m_total_vsize = std::accumulate(workspaces.cbegin(), workspaces.cend(), int64_t{0},1494[](int64_t sum, auto& ws) { return sum + ws.m_vsize; });1495m_subpackage.m_total_modified_fees = std::accumulate(workspaces.cbegin(), workspaces.cend(), CAmount{0},1496[](CAmount sum, auto& ws) { return sum + ws.m_modified_fees; });1497const CFeeRate package_feerate(m_subpackage.m_total_modified_fees, m_subpackage.m_total_vsize);1498std::vector<Wtxid> all_package_wtxids;1499all_package_wtxids.reserve(workspaces.size());1500std::transform(workspaces.cbegin(), workspaces.cend(), std::back_inserter(all_package_wtxids),