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.
1// Copyright (c) 2009-2010 Satoshi Nakamoto2// Copyright (c) 2009-present The Bitcoin Core developers3// Distributed under the MIT software license, see the accompanying4// file COPYING or http://www.opensource.org/licenses/mit-license.php.6#ifndef BITCOIN_COINS_H7#define BITCOIN_COINS_H9#include <attributes.h>10#include <compressor.h>11#include <core_memusage.h>12#include <crypto/siphash.h>13#include <memusage.h>14#include <primitives/transaction.h>15#include <primitives/transaction_identifier.h>16#include <serialize.h>17#include <support/allocators/pool.h>18#include <uint256.h>19#include <util/check.h>20#include <util/log.h>21#include <util/overflow.h>23#include <cassert>24#include <cstdint>26#include <atomic>27#include <functional>28#include <future>29#include <memory>30#include <optional>31#include <unordered_map>32#include <utility>33#include <vector>35class CBlock;36class ThreadPool;38/**39* A UTXO entry.40*41* Serialized format:42* - VARINT((height << 1) | (coinbase ? 1 : 0))43* - the non-spent CTxOut (via TxOutCompression)44*/45class Coin46{47public:48//! unspent transaction output49CTxOut out;51//! whether containing transaction was a coinbase52bool fCoinBase : 1;54//! at which height this containing transaction was included in the active block chain55uint32_t nHeight : 31;57//! construct a Coin from a CTxOut and height/coinbase information.58Coin(CTxOut&& outIn, int nHeightIn, bool fCoinBaseIn) : out(std::move(outIn)), fCoinBase(fCoinBaseIn), nHeight(nHeightIn) {}59Coin(const CTxOut& outIn, int nHeightIn, bool fCoinBaseIn) : out(outIn), fCoinBase(fCoinBaseIn),nHeight(nHeightIn) {}61void Clear() {62out.SetNull();63fCoinBase = false;64nHeight = 0;65}67//! empty constructor68Coin() : fCoinBase(false), nHeight(0) { }70bool IsCoinBase() const {71return fCoinBase;72}74template<typename Stream>75void Serialize(Stream &s) const {76assert(!IsSpent());77uint32_t code{(uint32_t{nHeight} << 1) | uint32_t{fCoinBase}};78::Serialize(s, VARINT(code));79::Serialize(s, Using<TxOutCompression>(out));80}82template<typename Stream>83void Unserialize(Stream &s) {84uint32_t code = 0;85::Unserialize(s, VARINT(code));86nHeight = code >> 1;87fCoinBase = code & 1;88::Unserialize(s, Using<TxOutCompression>(out));89}91/** Either this coin never existed (see e.g. coinEmpty in coins.cpp), or it92* did exist and has been spent.93*/94bool IsSpent() const {95return out.IsNull();96}98size_t DynamicMemoryUsage() const {99return memusage::DynamicUsage(out.scriptPubKey);100}101};103struct CCoinsCacheEntry;104using CoinsCachePair = std::pair<const COutPoint, CCoinsCacheEntry>;106/**107* A Coin in one level of the coins database caching hierarchy.108*109* A coin can either be:110* - unspent or spent (in which case the Coin object will be nulled out - see Coin.Clear())111* - DIRTY or not DIRTY112* - FRESH or not FRESH113*114* Out of these 2^3 = 8 states, only some combinations are valid:115* - unspent, FRESH, DIRTY (e.g. a new coin created in the cache)116* - unspent, not FRESH, DIRTY (e.g. a coin changed in the cache during a reorg)117* - unspent, not FRESH, not DIRTY (e.g. an unspent coin fetched from the parent cache)118* - spent, not FRESH, DIRTY (e.g. a coin is spent and spentness needs to be flushed to the parent)119*/120struct CCoinsCacheEntry121{122private:123/**124* These are used to create a doubly linked list of flagged entries.125* They are set in SetDirty, SetFresh, and unset in SetClean.126* A flagged entry is any entry that is either DIRTY, FRESH, or both.127*128* DIRTY entries are tracked so that only modified entries can be passed to129* the parent cache for batch writing. This is a performance optimization130* compared to giving all entries in the cache to the parent and having the131* parent scan for only modified entries.132*/133CoinsCachePair* m_prev{nullptr};134CoinsCachePair* m_next{nullptr};135uint8_t m_flags{0};137//! Adding a flag requires a reference to the sentinel of the flagged pair linked list.138static void AddFlags(uint8_t flags, CoinsCachePair& pair, CoinsCachePair& sentinel) noexcept139{140Assume(flags & (DIRTY | FRESH));141if (!pair.second.m_flags) {142Assume(!pair.second.m_prev && !pair.second.m_next);143pair.second.m_prev = sentinel.second.m_prev;144pair.second.m_next = &sentinel;145sentinel.second.m_prev = &pair;146pair.second.m_prev->second.m_next = &pair;147}148Assume(pair.second.m_prev && pair.second.m_next);149pair.second.m_flags |= flags;150}152public:153Coin coin; // The actual cached data.155enum Flags {156/**157* DIRTY means the CCoinsCacheEntry is potentially different from the158* version in the parent cache. Failure to mark a coin as DIRTY when159* it is potentially different from the parent cache will cause a160* consensus failure, since the coin's state won't get written to the161* parent when the cache is flushed.162*/163DIRTY = (1 << 0),164/**165* FRESH means the parent cache does not have this coin or that it is a166* spent coin in the parent cache. If a FRESH coin in the cache is167* later spent, it can be deleted entirely and doesn't ever need to be168* flushed to the parent. This is a performance optimization. Marking a169* coin as FRESH when it exists unspent in the parent cache will cause a170* consensus failure, since it might not be deleted from the parent171* when this cache is flushed.172*/173FRESH = (1 << 1),174};176CCoinsCacheEntry() noexcept = default;177explicit CCoinsCacheEntry(Coin&& coin_) noexcept : coin(std::move(coin_)) {}178~CCoinsCacheEntry()179{180SetClean();181}183static void SetDirty(CoinsCachePair& pair, CoinsCachePair& sentinel) noexcept { AddFlags(DIRTY, pair, sentinel); }184static void SetFresh(CoinsCachePair& pair, CoinsCachePair& sentinel) noexcept { AddFlags(FRESH, pair, sentinel); }186void SetClean() noexcept187{188if (!m_flags) return;189m_next->second.m_prev = m_prev;190m_prev->second.m_next = m_next;191m_flags = 0;192m_prev = m_next = nullptr;193}194bool IsDirty() const noexcept { return m_flags & DIRTY; }195bool IsFresh() const noexcept { return m_flags & FRESH; }197//! Only call Next when this entry is DIRTY, FRESH, or both198CoinsCachePair* Next() const noexcept199{200Assume(m_flags);201return m_next;202}204//! Only call Prev when this entry is DIRTY, FRESH, or both205CoinsCachePair* Prev() const noexcept206{207Assume(m_flags);208return m_prev;209}211//! Only use this for initializing the linked list sentinel212void SelfRef(CoinsCachePair& pair) noexcept213{214Assume(&pair.second == this);215m_prev = &pair;216m_next = &pair;217// Set sentinel to DIRTY so we can call Next on it218m_flags = DIRTY;219}220};222/**223* SipHash-1-3-UJ based hasher for the coins cache and related coins containers.224*225* Retained entries identify real transaction outputs, so their keys contain computed txids.226* Missing-input lookups may contain arbitrary claimed prevouts, but FetchCoin() immediately227* erases their temporary entries when the backend lookup fails, so non-hash keys cannot228* accumulate.229*230* The assumeutxo loader assumes snapshot txids are valid while loading and verifies the231* complete snapshot's content hash before activation.232*233* Hash values are process-local and must not be persisted, serialized, or compared across234* processes.235*236* Having the hash noexcept lets libstdc++ recalculate it during rehash instead of storing it in237* each node.238*/239class SaltedCoinsCacheHasher240{241const SipHasher13UJ m_hasher;243public:244SaltedCoinsCacheHasher(bool deterministic = false);246/** Hash a transaction ID, itself a cryptographic hash, as one jumbo block. */247size_t operator()(const Txid& id) const noexcept248{249return m_hasher.Hash(id.ToUint256());250}