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.
2001if (!tx.IsCoinBase()) {2002txundo.vprevout.reserve(tx.vin.size());2003for (const CTxIn &txin : tx.vin) {2004txundo.vprevout.emplace_back();2005bool is_spent = inputs.SpendCoin(txin.prevout, &txundo.vprevout.back());2006assert(is_spent);2007}2008}2009// add outputs2010AddCoins(inputs, tx, nHeight);2011}2013std::optional<std::pair<ScriptError, std::string>> CScriptCheck::operator()() {2014const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;2015const CScriptWitness *witness = &ptxTo->vin[nIn].scriptWitness;2016ScriptError error{SCRIPT_ERR_UNKNOWN_ERROR};2017if (VerifyScript(scriptSig, m_tx_out.scriptPubKey, witness, m_flags, CachingTransactionSignatureChecker(ptxTo, nIn, m_tx_out.nValue, cacheStore, *m_signature_cache, *txdata), &error)) {2018return std::nullopt;2019} else {2020auto debug_str = strprintf("input %i of %s (wtxid %s), spending %s:%i", nIn, ptxTo->GetHash().ToString(), ptxTo->GetWitnessHash().ToString(), ptxTo->vin[nIn].prevout.hash.ToString(), ptxTo->vin[nIn].prevout.n);2021return std::make_pair(error, std::move(debug_str));2022}2023}2025ValidationCache::ValidationCache(const size_t script_execution_cache_bytes, const size_t signature_cache_bytes)2026: m_signature_cache{signature_cache_bytes}2027{2028// Setup the salted hasher2029uint256 nonce = GetRandHash();2030// We want the nonce to be 64 bytes long to force the hasher to process2031// this chunk, which makes later hash computations more efficient. We2032// just write our 32-byte entropy twice to fill the 64 bytes.2033m_script_execution_cache_hasher.Write(nonce.begin(), 32);2034m_script_execution_cache_hasher.Write(nonce.begin(), 32);2036const auto [num_elems, approx_size_bytes] = m_script_execution_cache.setup_bytes(script_execution_cache_bytes);2037LogInfo("Using %zu MiB out of %zu MiB requested for script execution cache, able to store %zu elements",2038approx_size_bytes >> 20, script_execution_cache_bytes >> 20, num_elems);2039}2041/**2042* Check whether all of this transaction's input scripts succeed.2043*2044* This involves ECDSA signature checks so can be computationally intensive. This function should2045* only be called after the cheap sanity checks in CheckTxInputs passed.2046*2047* If pvChecks is not nullptr, script checks are pushed onto it instead of being performed inline. Any2048* script checks which are not necessary (eg due to script execution cache hits) are, obviously,2049* not pushed onto pvChecks/run.2050*2051* Setting cacheSigStore/cacheFullScriptStore to false will remove elements from the corresponding cache2052* which are matched. This is useful for checking blocks where we will likely never need the cache2053* entry again.2054*2055* Note that we may set state.reason to NOT_STANDARD for extra soft-fork flags in flags, block-checking2056* callers should probably reset it to CONSENSUS in such cases.2057*2058* Non-static (and redeclared) in src/test/txvalidationcache_tests.cpp2059*/2060bool CheckInputScripts(const CTransaction& tx, TxValidationState& state,2061const CCoinsViewCache& inputs, script_verify_flags flags, bool cacheSigStore,2062bool cacheFullScriptStore, PrecomputedTransactionData& txdata,2063ValidationCache& validation_cache,2064std::vector<CScriptCheck>* pvChecks)2065{2066if (tx.IsCoinBase()) return true;2068if (pvChecks) {2069pvChecks->reserve(tx.vin.size());2070}2072// First check if script executions have been cached with the same2073// flags. Note that this assumes that the inputs provided are2074// correct (ie that the transaction hash which is in tx's prevouts2075// properly commits to the scriptPubKey in the inputs view of that2076// transaction).2077uint256 hashCacheEntry;2078CSHA256 hasher = validation_cache.ScriptExecutionCacheHasher();2079hasher.Write(UCharCast(tx.GetWitnessHash().begin()), 32).Write((unsigned char*)&flags, sizeof(flags)).Finalize(hashCacheEntry.begin());2080AssertLockHeld(cs_main); //TODO: Remove this requirement by making CuckooCache not require external locks2081if (validation_cache.m_script_execution_cache.contains(hashCacheEntry, !cacheFullScriptStore)) {2082return true;2083}2085if (!txdata.m_spent_outputs_ready) {2086std::vector<CTxOut> spent_outputs;2087spent_outputs.reserve(tx.vin.size());2089for (const auto& txin : tx.vin) {2090const COutPoint& prevout = txin.prevout;2091const Coin& coin = inputs.AccessCoin(prevout);2092assert(!coin.IsSpent());2093spent_outputs.emplace_back(coin.out);2094}2095txdata.Init(tx, std::move(spent_outputs));2096}2097assert(txdata.m_spent_outputs.size() == tx.vin.size());2099for (unsigned int i = 0; i < tx.vin.size(); i++) {2101// We very carefully only pass in things to CScriptCheck which2102// are clearly committed to by tx' witness hash. This provides2103// a sanity check that our caching is not introducing consensus2104// failures through additional data in, eg, the coins being2105// spent being checked as a part of CScriptCheck.2107// Verify signature2108CScriptCheck check(txdata.m_spent_outputs[i], tx, validation_cache.m_signature_cache, i, flags, cacheSigStore, &txdata);2109if (pvChecks) {2110pvChecks->emplace_back(std::move(check));2111} else if (auto result = check(); result.has_value()) {2112// Tx failures never trigger disconnections/bans.2113// This is so that network splits aren't triggered2114// either due to non-consensus relay policies (such as2115// non-standard DER encodings or non-null dummy2116// arguments) or due to new consensus rules introduced in2117// soft forks.2118if (flags & STANDARD_NOT_MANDATORY_VERIFY_FLAGS) {2119return state.Invalid(TxValidationResult::TX_NOT_STANDARD, strprintf("mempool-script-verify-flag-failed (%s)", ScriptErrorString(result->first)), result->second);2120} else {2121return state.Invalid(TxValidationResult::TX_CONSENSUS, strprintf("block-script-verify-flag-failed (%s)", ScriptErrorString(result->first)), result->second);2122}2123}2124}2126if (cacheFullScriptStore && !pvChecks) {2127// We executed all of the provided scripts, and were told to2128// cache the result. Do so now.2129validation_cache.m_script_execution_cache.insert(hashCacheEntry);2130}2132return true;2133}2135bool FatalError(Notifications& notifications, BlockValidationState& state, const bilingual_str& message)2136{2137notifications.fatalError(message);2138return state.Error(message.original);2139}2141/**2142* Restore the UTXO in a Coin at a given COutPoint2143* @param undo The Coin to be restored.2144* @param view The coins view to which to apply the changes.2145* @param out The out point that corresponds to the tx input.2146* @return A DisconnectResult as an int2147*/2148int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out)2149{2150bool fClean = true;2152if (view.HaveCoin(out)) fClean = false; // overwriting transaction output2154if (undo.nHeight == 0) {2155// Missing undo metadata (height and coinbase). Older versions included this2156// information only in undo records for the last spend of a transactions'2157// outputs. This implies that it must be present for some other output of the same tx.2158const Coin& alternate = AccessByTxid(view, out.hash);2159if (!alternate.IsSpent()) {2160undo.nHeight = alternate.nHeight;2161undo.fCoinBase = alternate.fCoinBase;2162} else {2163return DISCONNECT_FAILED; // adding output for transaction without known metadata2164}2165}2166// If the coin already exists as an unspent coin in the cache, then the2167// possible_overwrite parameter to AddCoin must be set to true. We have2168// already checked whether an unspent coin exists above using HaveCoin, so2169// we don't need to guess. When fClean is false, an unspent coin already2170// existed and it is an overwrite.2171view.AddCoin(out, std::move(undo), !fClean);2173return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN;2174}2176/** Undo the effects of this block (with given index) on the UTXO set represented by coins.2177* When FAILED is returned, view is left in an indeterminate state. */2178DisconnectResult Chainstate::DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view)2179{2180AssertLockHeld(::cs_main);2181bool fClean = true;2183CBlockUndo blockUndo;2184if (!m_blockman.ReadBlockUndo(blockUndo, *pindex)) {2185LogError("DisconnectBlock(): failure reading undo data\n");2186return DISCONNECT_FAILED;2187}2189if (blockUndo.vtxundo.size() + 1 != block.vtx.size()) {2190LogError("DisconnectBlock(): block and undo data inconsistent\n");2191return DISCONNECT_FAILED;2192}2194// Ignore blocks that contain transactions which are 'overwritten' by later transactions,2195// unless those are already completely spent.2196// See https://github.com/bitcoin/bitcoin/issues/22596 for additional information.2197// Note: the blocks specified here are different than the ones used in ConnectBlock because DisconnectBlock2198// unwinds the blocks in reverse. As a result, the inconsistency is not discovered until the earlier2199// blocks with the duplicate coinbase transactions are disconnected.2200bool fEnforceBIP30 = !((pindex->nHeight==91722 && pindex->GetBlockHash() == uint256{"00000000000271a2dc26e7667f8419f2e15416dc6955e5a6c6cdf3f2574dd08e"}) ||2201(pindex->nHeight==91812 && pindex->GetBlockHash() == uint256{"00000000000af0aed4792b1acee3d966af36cf5def14935db8de83d6f9306f2f"}));2203// undo transactions in reverse order2204for (int i = block.vtx.size() - 1; i >= 0; i--) {2205const CTransaction &tx = *(block.vtx[i]);2206Txid hash = tx.GetHash();2207bool is_coinbase = tx.IsCoinBase();2208bool is_bip30_exception = (is_coinbase && !fEnforceBIP30);2210// Check that all outputs are available and match the outputs in the block itself2211// exactly.2212for (size_t o = 0; o < tx.vout.size(); o++) {2213if (!tx.vout[o].scriptPubKey.IsUnspendable()) {2214COutPoint out(hash, o);2215Coin coin;2216bool is_spent = view.SpendCoin(out, &coin);2217if (!is_spent || tx.vout[o] != coin.out || pindex->nHeight != coin.nHeight || is_coinbase != coin.IsCoinBase()) {2218if (!is_bip30_exception) {2219fClean = false; // transaction output mismatch2220}2221}2222}2223}2225// restore inputs2226if (i > 0) { // not coinbases2227CTxUndo &txundo = blockUndo.vtxundo[i-1];2228if (txundo.vprevout.size() != tx.vin.size()) {2229LogError("DisconnectBlock(): transaction and undo data inconsistent\n");2230return DISCONNECT_FAILED;2231}2232for (unsigned int j = tx.vin.size(); j > 0;) {2233--j;2234const COutPoint& out = tx.vin[j].prevout;2235int res = ApplyTxInUndo(std::move(txundo.vprevout[j]), view, out);2236if (res == DISCONNECT_FAILED) return DISCONNECT_FAILED;2237fClean = fClean && res != DISCONNECT_UNCLEAN;2238}2239// At this point, all of txundo.vprevout should have been moved out.2240}2241}2243// move best block pointer to prevout block2244view.SetBestBlock(pindex->pprev->GetBlockHash());2246return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN;2247}2249script_verify_flags GetBlockScriptFlags(const CBlockIndex& block_index, const ChainstateManager& chainman)2250{