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.
1751if (!m_pool.exists(tx->GetHash())) {1752package_state_final.Invalid(PackageValidationResult::PCKG_TX, "transaction failed");1753TxValidationState mempool_full_state;1754mempool_full_state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "mempool full");1755// Replace the previous result.1756results_final.erase(wtxid);1757results_final.emplace(wtxid, MempoolAcceptResult::Failure(mempool_full_state));1758}1759} else if (const auto it{individual_results_nonfinal.find(wtxid)}; it != individual_results_nonfinal.end()) {1760Assume(it->second.m_result_type == MempoolAcceptResult::ResultType::INVALID);1761// Interesting result from previous processing.1762results_final.emplace(wtxid, it->second);1763}1764}1765Assume(results_final.size() == package.size());1766return PackageMempoolAcceptResult(package_state_final, std::move(results_final));1767}1769} // anon namespace1771MempoolAcceptResult AcceptToMemoryPool(Chainstate& active_chainstate, const CTransactionRef& tx,1772int64_t accept_time, bool bypass_limits, bool test_accept)1773{1774AssertLockHeld(::cs_main);1775assert(active_chainstate.GetMempool() != nullptr);1776CTxMemPool& pool{*active_chainstate.GetMempool()};1778std::vector<COutPoint> coins_to_uncache;1780auto args = MemPoolAccept::ATMPArgs::SingleAccept(accept_time, bypass_limits, coins_to_uncache, test_accept);1781MempoolAcceptResult result = MemPoolAccept(pool, active_chainstate).AcceptSingleTransactionAndCleanup(tx, args);1783if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {1784// Remove coins that were not present in the coins cache before calling1785// AcceptSingleTransaction(); this is to prevent memory DoS in case we receive a large1786// number of invalid transactions that attempt to overrun the in-memory coins cache1787// (`CCoinsViewCache::cacheCoins`).1789for (const COutPoint& hashTx : coins_to_uncache)1790active_chainstate.CoinsTip().Uncache(hashTx);1791TRACEPOINT(mempool, rejected,1792tx->GetHash().data(),1793result.m_state.GetRejectReason().c_str()1794);1795}1796// After we've (potentially) uncached entries, ensure our coins cache is still within its size limits1797BlockValidationState state_dummy;1798active_chainstate.FlushStateToDisk(state_dummy, FlushStateMode::PERIODIC);1799return result;1800}1802PackageMempoolAcceptResult ProcessNewPackage(Chainstate& active_chainstate, CTxMemPool& pool,1803const Package& package, bool test_accept, const std::optional<CFeeRate>& client_maxfeerate)1804{1805AssertLockHeld(cs_main);1806assert(!package.empty());1807assert(std::all_of(package.cbegin(), package.cend(), [](const auto& tx){return tx != nullptr;}));1809std::vector<COutPoint> coins_to_uncache;1810auto result = [&]() EXCLUSIVE_LOCKS_REQUIRED(cs_main) {1811AssertLockHeld(cs_main);1812if (test_accept) {1813auto args = MemPoolAccept::ATMPArgs::PackageTestAccept(GetTime(), coins_to_uncache);1814return MemPoolAccept(pool, active_chainstate).AcceptMultipleTransactionsAndCleanup(package, args);1815} else {1816auto args = MemPoolAccept::ATMPArgs::PackageChildWithParents(GetTime(), coins_to_uncache, client_maxfeerate);1817return MemPoolAccept(pool, active_chainstate).AcceptPackage(package, args);1818}1819}();1821// Uncache coins pertaining to transactions that were not submitted to the mempool.1822if (test_accept || result.m_state.IsInvalid()) {1823for (const COutPoint& hashTx : coins_to_uncache) {1824active_chainstate.CoinsTip().Uncache(hashTx);1825}1826}1827// Ensure the coins cache is still within limits.1828BlockValidationState state_dummy;1829active_chainstate.FlushStateToDisk(state_dummy, FlushStateMode::PERIODIC);1830return result;1831}1833CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams)1834{1835int halvings = nHeight / consensusParams.nSubsidyHalvingInterval;1836// Force block reward to zero when right shift is undefined.1837if (halvings >= 64)1838return 0;1840CAmount nSubsidy = 50 * COIN;1841// Subsidy is cut in half every 210,000 blocks which will occur approximately every 4 years.1842nSubsidy >>= halvings;1843return nSubsidy;1844}1846CoinsViews::CoinsViews(DBParams db_params, CoinsViewOptions options)1847: m_dbview{std::move(db_params), std::move(options)},1848m_catcherview(&m_dbview) {}1850void CoinsViews::InitCache(int32_t prevoutfetch_threads)1851{1852AssertLockHeld(::cs_main);1853m_cacheview = std::make_unique<CCoinsViewCache>(&m_catcherview);1854auto thread_pool{std::make_shared<ThreadPool>("prevout")};1855if (prevoutfetch_threads > 0) {1856thread_pool->Start(prevoutfetch_threads);1857LogInfo("Block input prevout fetching uses %d additional threads", prevoutfetch_threads);1858}1859m_connect_block_view = std::make_unique<CoinsViewOverlay>(&*m_cacheview, std::move(thread_pool));1860}1862Chainstate::Chainstate(1863CTxMemPool* mempool,1864BlockManager& blockman,1865ChainstateManager& chainman,1866std::optional<uint256> from_snapshot_blockhash)1867: m_mempool(mempool),1868m_blockman(blockman),1869m_chainman(chainman),1870m_assumeutxo(from_snapshot_blockhash ? Assumeutxo::UNVALIDATED : Assumeutxo::VALIDATED),1871m_from_snapshot_blockhash(from_snapshot_blockhash) {}1873fs::path Chainstate::StoragePath() const1874{1875fs::path path{m_chainman.m_options.datadir / "chainstate"};1876if (m_from_snapshot_blockhash) {1877path += node::SNAPSHOT_CHAINSTATE_SUFFIX;1878}1879return path;1880}1882const CBlockIndex* Chainstate::SnapshotBase() const1883{1884if (!m_from_snapshot_blockhash) return nullptr;1885if (!m_cached_snapshot_base) m_cached_snapshot_base = Assert(m_chainman.m_blockman.LookupBlockIndex(*m_from_snapshot_blockhash));1886return m_cached_snapshot_base;1887}1889const CBlockIndex* Chainstate::TargetBlock() const1890{1891if (!m_target_blockhash) return nullptr;1892if (!m_cached_target_block) m_cached_target_block = Assert(m_chainman.m_blockman.LookupBlockIndex(*m_target_blockhash));1893return m_cached_target_block;1894}1896void Chainstate::SetTargetBlock(CBlockIndex* block)1897{1898if (block) {1899m_target_blockhash = block->GetBlockHash();1900} else {1901m_target_blockhash.reset();1902}1903m_cached_target_block = block;1904}1906void Chainstate::SetTargetBlockHash(uint256 block_hash)1907{1908m_target_blockhash = block_hash;1909m_cached_target_block = nullptr;1910}1912void Chainstate::InitCoinsDB(1913size_t cache_size_bytes,1914bool in_memory,1915bool should_wipe)1916{1917m_coins_views = std::make_unique<CoinsViews>(1918DBParams{1919.path = StoragePath(),1920.cache_bytes = cache_size_bytes,1921.memory_only = in_memory,1922.wipe_data = should_wipe,1923.obfuscate = true,1924.options = m_chainman.m_options.coins_db},1925m_chainman.m_options.coins_view);1927m_coinsdb_cache_size_bytes = cache_size_bytes;1928}1930void Chainstate::InitCoinsCache(size_t cache_size_bytes)1931{1932AssertLockHeld(::cs_main);1933assert(m_coins_views != nullptr);1934m_coinstip_cache_size_bytes = cache_size_bytes;1935m_coins_views->InitCache(m_chainman.m_options.prevoutfetch_threads_num);1936}1938// Lock-free: depends on `m_cached_is_ibd`, which is latched by `UpdateIBDStatus()`.1939bool ChainstateManager::IsInitialBlockDownload() const noexcept1940{1941return m_cached_is_ibd.load(std::memory_order_relaxed);1942}1944void Chainstate::CheckForkWarningConditions()1945{1946AssertLockHeld(cs_main);1948if (this->GetRole().historical) {1949return;1950}1952if (m_chainman.m_best_invalid && m_chainman.m_best_invalid->nChainWork > m_chain.Tip()->nChainWork + (GetBlockProof(*m_chain.Tip()) * 6)) {1953LogWarning("Found invalid chain more than 6 blocks longer than our best chain. This could be due to database corruption or consensus incompatibility with peers.");1954m_chainman.GetNotifications().warningSet(1955kernel::Warning::LARGE_WORK_INVALID_CHAIN,1956_("Warning: Found invalid chain more than 6 blocks longer than our best chain. This could be due to database corruption or consensus incompatibility with peers."));1957} else {1958m_chainman.GetNotifications().warningUnset(kernel::Warning::LARGE_WORK_INVALID_CHAIN);1959}1960}1962// Called both upon regular invalid block discovery *and* InvalidateBlock1963void Chainstate::InvalidChainFound(CBlockIndex* pindexNew)1964{1965AssertLockHeld(cs_main);1966if (!m_chainman.m_best_invalid || pindexNew->nChainWork > m_chainman.m_best_invalid->nChainWork) {1967m_chainman.m_best_invalid = pindexNew;1968}1969SetBlockFailureFlags(pindexNew);1970if (m_chainman.m_best_header != nullptr && m_chainman.m_best_header->GetAncestor(pindexNew->nHeight) == pindexNew) {1971m_chainman.RecalculateBestHeader();1972}1974LogInfo("%s: invalid block=%s height=%d log2_work=%f date=%s", __func__,1975pindexNew->GetBlockHash().ToString(), pindexNew->nHeight,1976log(pindexNew->nChainWork.getdouble())/log(2.0), FormatISO8601DateTime(pindexNew->GetBlockTime()));1977CBlockIndex *tip = m_chain.Tip();1978assert (tip);1979LogInfo("%s: current best=%s height=%d log2_work=%f date=%s", __func__,1980tip->GetBlockHash().ToString(), m_chain.Height(), log(tip->nChainWork.getdouble())/log(2.0),1981FormatISO8601DateTime(tip->GetBlockTime()));1982CheckForkWarningConditions();1983}1985// Same as InvalidChainFound, above, except not called directly from InvalidateBlock,1986// which does its own setBlockIndexCandidates management.1987void Chainstate::InvalidBlockFound(CBlockIndex* pindex, const BlockValidationState& state)1988{1989AssertLockHeld(cs_main);1990if (state.GetResult() != BlockValidationResult::BLOCK_MUTATED) {1991pindex->nStatus |= BLOCK_FAILED_VALID;1992m_blockman.m_dirty_blockindex.insert(pindex);1993setBlockIndexCandidates.erase(pindex);1994InvalidChainFound(pindex);1995}1996}1998void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txundo, int nHeight)1999{2000// mark inputs spent