LCOV - code coverage report
Current view: top level - src - coins.h (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 92.8 % 167 155
Test Date: 2026-07-25 07:01:57 Functions: 76.5 % 34 26
Branches: 60.8 % 656 399

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2                 :             : // Copyright (c) 2009-present The Bitcoin Core developers
       3                 :             : // Distributed under the MIT software license, see the accompanying
       4                 :             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5                 :             : 
       6                 :             : #ifndef BITCOIN_COINS_H
       7                 :             : #define BITCOIN_COINS_H
       8                 :             : 
       9                 :             : #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>
      22                 :             : 
      23                 :             : #include <cassert>
      24                 :             : #include <cstdint>
      25                 :             : 
      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>
      34                 :             : 
      35                 :             : class CBlock;
      36                 :             : class ThreadPool;
      37                 :             : 
      38                 :             : /**
      39                 :             :  * A UTXO entry.
      40                 :             :  *
      41                 :             :  * Serialized format:
      42                 :             :  * - VARINT((height << 1) | (coinbase ? 1 : 0))
      43                 :             :  * - the non-spent CTxOut (via TxOutCompression)
      44                 :             :  */
      45   [ +  +  +  -  :    67283645 : class Coin
          -  -  -  -  +  
           - ][ +  +  +  
          -  +  -  +  -  
           +  - ][ +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          -  +  -  -  +  
          -  +  -  +  -  
          +  -  -  +  -  
          -  +  -  +  -  
          +  -  +  -  +  
                      + ]
      46                 :             : {
      47                 :             : public:
      48                 :             :     //! unspent transaction output
      49                 :             :     CTxOut out;
      50                 :             : 
      51                 :             :     //! whether containing transaction was a coinbase
      52                 :             :     bool fCoinBase : 1;
      53                 :             : 
      54                 :             :     //! at which height this containing transaction was included in the active block chain
      55                 :             :     uint32_t nHeight : 31;
      56                 :             : 
      57                 :             :     //! construct a Coin from a CTxOut and height/coinbase information.
      58         [ +  + ]:          66 :     Coin(CTxOut&& outIn, int nHeightIn, bool fCoinBaseIn) : out(std::move(outIn)), fCoinBase(fCoinBaseIn), nHeight(nHeightIn) {}
      59         [ +  - ]:    15039360 :     Coin(const CTxOut& outIn, int nHeightIn, bool fCoinBaseIn) : out(outIn), fCoinBase(fCoinBaseIn),nHeight(nHeightIn) {}
           [ +  +  +  + ]
      60                 :             : 
      61                 :     9231539 :     void Clear() {
      62                 :     9231539 :         out.SetNull();
      63                 :     9231539 :         fCoinBase = false;
      64   [ -  +  +  +  :     9231539 :         nHeight = 0;
                   +  - ]
      65                 :     9163511 :     }
      66                 :             : 
      67                 :             :     //! empty constructor
      68   [ +  -  #  # ]:    58482400 :     Coin() : fCoinBase(false), nHeight(0) { }
           [ +  -  +  -  
           +  - ][ +  -  
             +  +  #  # ]
           [ +  -  +  -  
          +  -  -  +  -  
                +  +  + ]
      69                 :             : 
      70                 :     9624650 :     bool IsCoinBase() const {
      71   [ +  +  #  #  :     9624650 :         return fCoinBase;
           #  # ][ +  +  
             +  +  +  + ]
           [ +  -  +  - ]
      72                 :             :     }
      73                 :             : 
      74                 :             :     template<typename Stream>
      75                 :      318814 :     void Serialize(Stream &s) const {
      76         [ -  + ]:      318814 :         assert(!IsSpent());
      77                 :      318814 :         uint32_t code{(uint32_t{nHeight} << 1) | uint32_t{fCoinBase}};
      78                 :      318814 :         ::Serialize(s, VARINT(code));
      79                 :      318814 :         ::Serialize(s, Using<TxOutCompression>(out));
      80                 :      318814 :     }
      81                 :             : 
      82                 :             :     template<typename Stream>
      83                 :      364383 :     void Unserialize(Stream &s) {
      84                 :      364383 :         uint32_t code = 0;
      85                 :      364383 :         ::Unserialize(s, VARINT(code));
      86                 :      364383 :         nHeight = code >> 1;
      87                 :      364383 :         fCoinBase = code & 1;
      88                 :      364383 :         ::Unserialize(s, Using<TxOutCompression>(out));
      89                 :      364381 :     }
      90                 :             : 
      91                 :             :     /** Either this coin never existed (see e.g. coinEmpty in coins.cpp), or it
      92                 :             :       * did exist and has been spent.
      93                 :             :       */
      94         [ +  - ]:    93873572 :     bool IsSpent() const {
      95 [ +  + ][ +  +  :    93181112 :         return out.IsNull();
             +  +  -  + ]
           [ +  +  +  +  
          +  +  +  +  +  
           - ][ -  +  +  
          +  +  -  -  +  
           -  + ][ +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  -  +  +  
          +  +  +  -  +  
           +  + ][ +  -  
          +  -  +  -  +  
          -  +  +  -  +  
          +  -  +  -  +  
          -  +  +  +  +  
          +  +  +  +  +  
          -  +  +  +  +  
          +  +  +  +  -  
                      + ]
      96                 :             :     }
      97                 :             : 
      98                 :    35887791 :     size_t DynamicMemoryUsage() const {
      99   [ +  +  +  +  :    36677180 :         return memusage::DynamicUsage(out.scriptPubKey);
          +  +  +  -  -  
          +  -  -  +  +  
          +  +  +  +  +  
          +  +  +  +  -  
          +  -  +  +  +  
          +  +  +  +  -  
          +  +  +  +  +  
          -  +  +  +  +  
                   -  + ]
           [ -  +  +  + ]
     100                 :             :     }
     101                 :             : };
     102                 :             : 
     103                 :             : struct CCoinsCacheEntry;
     104                 :             : using CoinsCachePair = std::pair<const COutPoint, CCoinsCacheEntry>;
     105                 :             : 
     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 DIRTY
     112                 :             :  * - FRESH or not FRESH
     113                 :             :  *
     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                 :             :  */
     120                 :             : struct CCoinsCacheEntry
     121                 :             : {
     122                 :             : private:
     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 to
     129                 :             :      * the parent cache for batch writing. This is a performance optimization
     130                 :             :      * compared to giving all entries in the cache to the parent and having the
     131                 :             :      * parent scan for only modified entries.
     132                 :             :      */
     133                 :             :     CoinsCachePair* m_prev{nullptr};
     134                 :             :     CoinsCachePair* m_next{nullptr};
     135                 :             :     uint8_t m_flags{0};
     136                 :             : 
     137                 :             :     //! Adding a flag requires a reference to the sentinel of the flagged pair linked list.
     138                 :    39083347 :     static void AddFlags(uint8_t flags, CoinsCachePair& pair, CoinsCachePair& sentinel) noexcept
     139                 :             :     {
     140         [ +  + ]:    39083347 :         Assume(flags & (DIRTY | FRESH));
     141         [ +  + ]:    39083347 :         if (!pair.second.m_flags) {
     142                 :    24375285 :             Assume(!pair.second.m_prev && !pair.second.m_next);
     143                 :    24375285 :             pair.second.m_prev = sentinel.second.m_prev;
     144                 :    24375285 :             pair.second.m_next = &sentinel;
     145                 :    24375285 :             sentinel.second.m_prev = &pair;
     146                 :    24375285 :             pair.second.m_prev->second.m_next = &pair;
     147                 :             :         }
     148                 :    39083347 :         Assume(pair.second.m_prev && pair.second.m_next);
     149                 :    39083347 :         pair.second.m_flags |= flags;
     150                 :    39083347 :     }
     151                 :             : 
     152                 :             : public:
     153                 :             :     Coin coin; // The actual cached data.
     154                 :             : 
     155                 :             :     enum Flags {
     156                 :             :         /**
     157                 :             :          * DIRTY means the CCoinsCacheEntry is potentially different from the
     158                 :             :          * version in the parent cache. Failure to mark a coin as DIRTY when
     159                 :             :          * it is potentially different from the parent cache will cause a
     160                 :             :          * consensus failure, since the coin's state won't get written to the
     161                 :             :          * parent when the cache is flushed.
     162                 :             :          */
     163                 :             :         DIRTY = (1 << 0),
     164                 :             :         /**
     165                 :             :          * FRESH means the parent cache does not have this coin or that it is a
     166                 :             :          * spent coin in the parent cache. If a FRESH coin in the cache is
     167                 :             :          * later spent, it can be deleted entirely and doesn't ever need to be
     168                 :             :          * flushed to the parent. This is a performance optimization. Marking a
     169                 :             :          * coin as FRESH when it exists unspent in the parent cache will cause a
     170                 :             :          * consensus failure, since it might not be deleted from the parent
     171                 :             :          * when this cache is flushed.
     172                 :             :          */
     173                 :             :         FRESH = (1 << 1),
     174                 :             :     };
     175                 :             : 
     176                 :    54510770 :     CCoinsCacheEntry() noexcept = default;
     177                 :       25350 :     explicit CCoinsCacheEntry(Coin&& coin_) noexcept : coin(std::move(coin_)) {}
     178                 :    54536440 :     ~CCoinsCacheEntry()
     179                 :             :     {
     180                 :   109072880 :         SetClean();
     181                 :    54536440 :     }
     182                 :             : 
     183                 :    24382326 :     static void SetDirty(CoinsCachePair& pair, CoinsCachePair& sentinel) noexcept { AddFlags(DIRTY, pair, sentinel); }
     184                 :    14701021 :     static void SetFresh(CoinsCachePair& pair, CoinsCachePair& sentinel) noexcept { AddFlags(FRESH, pair, sentinel); }
     185                 :             : 
     186                 :    54607526 :     void SetClean() noexcept
     187                 :             :     {
     188 [ +  + ][ +  -  :    54536446 :         if (!m_flags) return;
          -  +  +  -  -  
                      - ]
     189                 :    24805540 :         m_next->second.m_prev = m_prev;
     190                 :    24805540 :         m_prev->second.m_next = m_next;
     191                 :    24805540 :         m_flags = 0;
     192                 :    24805540 :         m_prev = m_next = nullptr;
     193                 :             :     }
     194 [ +  - ][ +  -  :    26015968 :     bool IsDirty() const noexcept { return m_flags & DIRTY; }
          +  +  +  +  -  
          +  +  +  +  +  
          +  +  +  -  +  
           - ][ +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
     195   [ +  +  +  +  :    10330176 :     bool IsFresh() const noexcept { return m_flags & FRESH; }
          +  +  +  +  +  
              + ][ +  + ]
     196                 :             : 
     197                 :             :     //! Only call Next when this entry is DIRTY, FRESH, or both
     198                 :     1262089 :     CoinsCachePair* Next() const noexcept
     199                 :             :     {
     200 [ -  + ][ +  -  :     1054098 :         Assume(m_flags);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     201 [ -  + ][ +  -  :      211332 :         return m_next;
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     202                 :             :     }
     203                 :             : 
     204                 :             :     //! Only call Prev when this entry is DIRTY, FRESH, or both
     205                 :      103975 :     CoinsCachePair* Prev() const noexcept
     206                 :             :     {
     207 [ -  + ][ +  -  :       52007 :         Assume(m_flags);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
     208   [ -  +  -  + ]:       52007 :         return m_prev;
           [ +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
     209                 :             :     }
     210                 :             : 
     211                 :             :     //! Only use this for initializing the linked list sentinel
     212                 :      430255 :     void SelfRef(CoinsCachePair& pair) noexcept
     213                 :             :     {
     214 [ +  - ][ +  -  :      430255 :         Assume(&pair.second == this);
             +  -  +  - ]
     215                 :      430255 :         m_prev = &pair;
     216                 :      430255 :         m_next = &pair;
     217                 :             :         // Set sentinel to DIRTY so we can call Next on it
     218 [ +  - ][ +  -  :      430255 :         m_flags = DIRTY;
             +  -  +  - ]
     219                 :             :     }
     220                 :             : };
     221                 :             : 
     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() immediately
     227                 :             :  * erases their temporary entries when the backend lookup fails, so non-hash keys cannot
     228                 :             :  * accumulate.
     229                 :             :  *
     230                 :             :  * The assumeutxo loader assumes snapshot txids are valid while loading and verifies the
     231                 :             :  * complete snapshot's content hash before activation.
     232                 :             :  *
     233                 :             :  * Hash values are process-local and must not be persisted, serialized, or compared across
     234                 :             :  * processes.
     235                 :             :  *
     236                 :             :  * Having the hash noexcept lets libstdc++ recalculate it during rehash instead of storing it in
     237                 :             :  * each node.
     238                 :             :  */
     239                 :             : class SaltedCoinsCacheHasher
     240                 :             : {
     241                 :             :     const SipHasher13UJ m_hasher;
     242                 :             : 
     243                 :             : public:
     244                 :             :     SaltedCoinsCacheHasher(bool deterministic = false);
     245                 :             : 
     246                 :             :     /** Hash a transaction ID, itself a cryptographic hash, as one jumbo block. */
     247                 :      198884 :     size_t operator()(const Txid& id) const noexcept
     248                 :             :     {
     249                 :      198884 :         return m_hasher.Hash(id.ToUint256());
     250                 :             :     }
     251                 :             : 
     252                 :             :     /** Hash an outpoint as its txid jumbo block followed by the zero-extended index as one normal block. */
     253                 :   250698040 :     size_t operator()(const COutPoint& id) const noexcept
     254                 :             :     {
     255                 :   250698040 :         return m_hasher.Hash(id.hash.ToUint256(), uint64_t{id.n});
     256                 :             :     }
     257                 :             : };
     258                 :             : 
     259                 :             : /**
     260                 :             :  * PoolAllocator's MAX_BLOCK_SIZE_BYTES parameter here uses sizeof the data, and adds the size
     261                 :             :  * of 4 pointers. We do not know the exact node size used in the std::unordered_node implementation
     262                 :             :  * because it is implementation defined. Most implementations have an overhead of 1 or 2 pointers,
     263                 :             :  * so nodes can be connected in a linked list, and in some cases the hash value is stored as well.
     264                 :             :  * Using an additional sizeof(void*)*4 for MAX_BLOCK_SIZE_BYTES should thus be sufficient so that
     265                 :             :  * all implementations can allocate the nodes from the PoolAllocator.
     266                 :             :  */
     267                 :             : using CCoinsMap = std::unordered_map<COutPoint,
     268                 :             :                                      CCoinsCacheEntry,
     269                 :             :                                      SaltedCoinsCacheHasher,
     270                 :             :                                      std::equal_to<COutPoint>,
     271                 :             :                                      PoolAllocator<CoinsCachePair,
     272                 :             :                                                    sizeof(CoinsCachePair) + sizeof(void*) * 4>>;
     273                 :             : 
     274                 :             : using CCoinsMapMemoryResource = CCoinsMap::allocator_type::ResourceType;
     275                 :             : 
     276                 :             : /** Cursor for iterating over CoinsView state */
     277                 :             : class CCoinsViewCursor
     278                 :             : {
     279                 :             : public:
     280                 :        1252 :     CCoinsViewCursor(const uint256& in_block_hash) : block_hash(in_block_hash) {}
     281                 :        1252 :     virtual ~CCoinsViewCursor() = default;
     282                 :             : 
     283                 :             :     virtual bool GetKey(COutPoint &key) const = 0;
     284                 :             :     virtual bool GetValue(Coin &coin) const = 0;
     285                 :             : 
     286                 :             :     virtual bool Valid() const = 0;
     287                 :             :     virtual void Next() = 0;
     288                 :             : 
     289                 :             :     //! Get best block at the time this cursor was created
     290   [ +  -  +  -  :         104 :     const uint256& GetBestBlock() const { return block_hash; }
                   +  - ]
     291                 :             : private:
     292                 :             :     uint256 block_hash;
     293                 :             : };
     294                 :             : 
     295                 :             : /**
     296                 :             :  * Cursor for iterating over the linked list of flagged entries in CCoinsViewCache.
     297                 :             :  *
     298                 :             :  * This is a helper struct to encapsulate the diverging logic between a non-erasing
     299                 :             :  * CCoinsViewCache::Sync and an erasing CCoinsViewCache::Flush. This allows the receiver
     300                 :             :  * of CCoinsView::BatchWrite to iterate through the flagged entries without knowing
     301                 :             :  * the caller's intent.
     302                 :             :  *
     303                 :             :  * However, the receiver can still call CoinsViewCacheCursor::WillErase to see if the
     304                 :             :  * caller will erase the entry after BatchWrite returns. If so, the receiver can
     305                 :             :  * perform optimizations such as moving the coin out of the CCoinsCachEntry instead
     306                 :             :  * of copying it.
     307                 :             :  */
     308                 :             : struct CoinsViewCacheCursor
     309                 :             : {
     310                 :             :     //! If will_erase is not set, iterating through the cursor will erase spent coins from the map,
     311                 :             :     //! and other coins will be unflagged (removing them from the linked list).
     312                 :             :     //! If will_erase is set, the underlying map and linked list will not be modified,
     313                 :             :     //! as the caller is expected to wipe the entire map anyway.
     314                 :             :     //! This is an optimization compared to erasing all entries as the cursor iterates them when will_erase is set.
     315                 :             :     //! Calling CCoinsMap::clear() afterwards is faster because a CoinsCachePair cannot be coerced back into a
     316                 :             :     //! CCoinsMap::iterator to be erased, and must therefore be looked up again by key in the CCoinsMap before being erased.
     317                 :      157484 :     CoinsViewCacheCursor(size_t& dirty_count LIFETIMEBOUND,
     318                 :             :                          CoinsCachePair& sentinel LIFETIMEBOUND,
     319                 :             :                          CCoinsMap& map LIFETIMEBOUND,
     320                 :             :                          bool will_erase) noexcept
     321         [ +  + ]:      157484 :         : m_dirty_count(dirty_count), m_sentinel(sentinel), m_map(map), m_will_erase(will_erase) {}
     322                 :             : 
     323                 :      157484 :     inline CoinsCachePair* Begin() const noexcept { return m_sentinel.second.Next(); }
     324         [ +  + ]:     1104305 :     inline CoinsCachePair* End() const noexcept { return &m_sentinel; }
     325                 :             : 
     326                 :             :     //! Return the next entry after current, possibly erasing current
     327                 :      946821 :     inline CoinsCachePair* NextAndMaybeErase(CoinsCachePair& current) noexcept
     328                 :             :     {
     329         [ +  - ]:      946821 :         const auto next_entry{current.second.Next()};
     330   [ +  -  +  + ]:     1893642 :         Assume(TrySub(m_dirty_count, current.second.IsDirty()));
     331                 :             :         // If we are not going to erase the cache, we must still erase spent entries.
     332                 :             :         // Otherwise, clear the state of the entry.
     333         [ +  + ]:      946821 :         if (!m_will_erase) {
     334         [ +  + ]:       92817 :             if (current.second.coin.IsSpent()) {
     335   [ -  +  -  - ]:       21737 :                 assert(current.second.coin.DynamicMemoryUsage() == 0); // scriptPubKey was already cleared in SpendCoin
     336                 :       21737 :                 m_map.erase(current.first);
     337                 :             :             } else {
     338         [ +  - ]:       71080 :                 current.second.SetClean();
     339                 :             :             }
     340                 :             :         }
     341                 :      946821 :         return next_entry;
     342                 :             :     }
     343                 :             : 
     344   [ +  +  +  +  :      481586 :     inline bool WillErase(CoinsCachePair& current) const noexcept { return m_will_erase || current.second.coin.IsSpent(); }
             +  +  +  + ]
     345                 :        3928 :     size_t GetDirtyCount() const noexcept { return m_dirty_count; }
     346         [ +  - ]:        3928 :     size_t GetTotalCount() const noexcept { return m_map.size(); }
     347                 :             : private:
     348                 :             :     size_t& m_dirty_count;
     349                 :             :     CoinsCachePair& m_sentinel;
     350                 :             :     CCoinsMap& m_map;
     351                 :             :     bool m_will_erase;
     352                 :             : };
     353                 :             : 
     354                 :             : /** Pure abstract view on the open txout dataset. */
     355                 :      482320 : class CCoinsView
     356                 :             : {
     357                 :             : public:
     358                 :             :     //! As we use CCoinsViews polymorphically, have a virtual destructor
     359                 :        1350 :     virtual ~CCoinsView() = default;
     360                 :             : 
     361                 :             :     //! Retrieve the Coin (unspent transaction output) for a given outpoint.
     362                 :             :     //! May populate the cache. Use PeekCoin() to perform a non-caching lookup.
     363                 :             :     virtual std::optional<Coin> GetCoin(const COutPoint& outpoint) const = 0;
     364                 :             : 
     365                 :             :     //! Retrieve the Coin (unspent transaction output) for a given outpoint, without caching results.
     366                 :             :     //! Does not populate the cache. Use GetCoin() to cache the result.
     367                 :             :     virtual std::optional<Coin> PeekCoin(const COutPoint& outpoint) const = 0;
     368                 :             : 
     369                 :             :     //! Just check whether a given outpoint is unspent.
     370                 :             :     //! May populate the cache. Use PeekCoin() to perform a non-caching lookup.
     371                 :             :     virtual bool HaveCoin(const COutPoint& outpoint) const = 0;
     372                 :             : 
     373                 :             :     //! Retrieve the block hash whose state this CCoinsView currently represents
     374                 :             :     virtual uint256 GetBestBlock() const = 0;
     375                 :             : 
     376                 :             :     //! Retrieve the range of blocks that may have been only partially written.
     377                 :             :     //! If the database is in a consistent state, the result is the empty vector.
     378                 :             :     //! Otherwise, a two-element vector is returned consisting of the new and
     379                 :             :     //! the old block hash, in that order.
     380                 :             :     virtual std::vector<uint256> GetHeadBlocks() const = 0;
     381                 :             : 
     382                 :             :     //! Do a bulk modification (multiple Coin changes + BestBlock change).
     383                 :             :     //! The passed cursor is used to iterate through the coins.
     384                 :             :     virtual void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& block_hash) = 0;
     385                 :             : 
     386                 :             :     //! Estimate database size
     387                 :             :     virtual size_t EstimateSize() const = 0;
     388                 :             : };
     389                 :             : 
     390                 :             : /** Noop coins view. */
     391                 :           4 : class CoinsViewEmpty : public CCoinsView
     392                 :             : {
     393                 :             : protected:
     394   [ +  -  +  -  :           4 :     CoinsViewEmpty() = default;
                   +  - ]
     395                 :             : 
     396                 :             : public:
     397                 :             :     static CoinsViewEmpty& Get();
     398                 :             : 
     399                 :             :     CoinsViewEmpty(const CoinsViewEmpty&) = delete;
     400                 :             :     CoinsViewEmpty& operator=(const CoinsViewEmpty&) = delete;
     401                 :             : 
     402                 :          29 :     std::optional<Coin> GetCoin(const COutPoint&) const override { return {}; }
     403                 :           1 :     std::optional<Coin> PeekCoin(const COutPoint& outpoint) const override { return GetCoin(outpoint); }
     404                 :           0 :     bool HaveCoin(const COutPoint& outpoint) const override { return !!GetCoin(outpoint); }
     405                 :           0 :     uint256 GetBestBlock() const override { return {}; }
     406                 :           0 :     std::vector<uint256> GetHeadBlocks() const override { return {}; }
     407                 :           0 :     void BatchWrite(CoinsViewCacheCursor& cursor, const uint256&) override
     408                 :             :     {
     409         [ #  # ]:           0 :         for (auto it{cursor.Begin()}; it != cursor.End(); it = cursor.NextAndMaybeErase(*it)) { }
     410                 :           0 :     }
     411                 :           0 :     size_t EstimateSize() const override { return 0; }
     412                 :             : };
     413                 :             : 
     414                 :             : /** CCoinsView backed by another CCoinsView */
     415                 :           0 : class CCoinsViewBacked : public CCoinsView
     416                 :             : {
     417                 :             : protected:
     418                 :             :     CCoinsView* base;
     419                 :             : 
     420                 :             : public:
     421         [ -  + ]:      480970 :     explicit CCoinsViewBacked(CCoinsView* in_view) : base{Assert(in_view)} {}
     422                 :             : 
     423   [ +  -  +  - ]:       85985 :     void SetBackend(CCoinsView& in_view) { base = &in_view; }
     424                 :             : 
     425                 :      921418 :     std::optional<Coin> GetCoin(const COutPoint& outpoint) const override { return base->GetCoin(outpoint); }
     426                 :      444933 :     std::optional<Coin> PeekCoin(const COutPoint& outpoint) const override { return base->PeekCoin(outpoint); }
     427                 :           0 :     bool HaveCoin(const COutPoint& outpoint) const override { return base->HaveCoin(outpoint); }
     428                 :       43822 :     uint256 GetBestBlock() const override { return base->GetBestBlock(); }
     429                 :           0 :     std::vector<uint256> GetHeadBlocks() const override { return base->GetHeadBlocks(); }
     430                 :        3629 :     void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& block_hash) override { base->BatchWrite(cursor, block_hash); }
     431                 :           0 :     size_t EstimateSize() const override { return base->EstimateSize(); }
     432                 :             : };
     433                 :             : 
     434                 :             : 
     435                 :             : /** CCoinsView that adds a memory cache for transactions to another CCoinsView */
     436                 :             : class CCoinsViewCache : public CCoinsViewBacked
     437                 :             : {
     438                 :             : private:
     439                 :             :     const bool m_deterministic;
     440                 :             : 
     441                 :             : protected:
     442                 :             :     /**
     443                 :             :      * Make mutable so that we can "fill the cache" even from Get-methods
     444                 :             :      * declared as "const".
     445                 :             :      */
     446                 :             :     mutable uint256 m_block_hash;
     447                 :             :     mutable CCoinsMapMemoryResource m_cache_coins_memory_resource{};
     448                 :             :     /* The starting sentinel of the flagged entry circular doubly linked list. */
     449                 :             :     mutable CoinsCachePair m_sentinel;
     450                 :             :     mutable CCoinsMap cacheCoins;
     451                 :             : 
     452                 :             :     /* Cached dynamic memory usage for the inner Coin objects. */
     453                 :             :     mutable size_t cachedCoinsUsage{0};
     454                 :             :     /* Running count of dirty Coin cache entries. */
     455                 :             :     mutable size_t m_dirty_count{0};
     456                 :             : 
     457                 :             :     /**
     458                 :             :      * Discard all modifications made to this cache without flushing to the base view.
     459                 :             :      * This can be used to efficiently reuse a cache instance across multiple operations.
     460                 :             :      */
     461                 :             :     virtual void Reset() noexcept;
     462                 :             : 
     463                 :             :     /* Fetch the coin from base. Used for cache misses in FetchCoin. */
     464                 :             :     virtual std::optional<Coin> FetchCoinFromBase(const COutPoint& outpoint) const;
     465                 :             : 
     466                 :             : public:
     467                 :             :     CCoinsViewCache(CCoinsView* in_base, bool deterministic = false);
     468                 :             : 
     469                 :             :     /**
     470                 :             :      * By deleting the copy constructor, we prevent accidentally using it when one intends to create a cache on top of a base cache.
     471                 :             :      */
     472                 :             :     CCoinsViewCache(const CCoinsViewCache &) = delete;
     473                 :             : 
     474                 :             :     // Standard CCoinsView methods
     475                 :             :     std::optional<Coin> GetCoin(const COutPoint& outpoint) const override;
     476                 :             :     std::optional<Coin> PeekCoin(const COutPoint& outpoint) const override;
     477                 :             :     bool HaveCoin(const COutPoint& outpoint) const override;
     478                 :             :     uint256 GetBestBlock() const override;
     479                 :             :     void SetBestBlock(const uint256& block_hash);
     480                 :             :     void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& block_hash) override;
     481                 :             : 
     482                 :             :     /**
     483                 :             :      * Check if we have the given utxo already loaded in this cache.
     484                 :             :      * The semantics are the same as HaveCoin(), but no calls to
     485                 :             :      * the backing CCoinsView are made.
     486                 :             :      */
     487                 :             :     bool HaveCoinInCache(const COutPoint &outpoint) const;
     488                 :             : 
     489                 :             :     /**
     490                 :             :      * Return a reference to Coin in the cache, or coinEmpty if not found. This is
     491                 :             :      * more efficient than GetCoin.
     492                 :             :      *
     493                 :             :      * Generally, do not hold the reference returned for more than a short scope.
     494                 :             :      * While the current implementation allows for modifications to the contents
     495                 :             :      * of the cache while holding the reference, this behavior should not be relied
     496                 :             :      * on! To be safe, best to not hold the returned reference through any other
     497                 :             :      * calls to this cache.
     498                 :             :      */
     499                 :             :     const Coin& AccessCoin(const COutPoint &output) const;
     500                 :             : 
     501                 :             :     /**
     502                 :             :      * Add a coin. Set possible_overwrite to true if an unspent version may
     503                 :             :      * already exist in the cache.
     504                 :             :      */
     505                 :             :     void AddCoin(const COutPoint& outpoint, Coin&& coin, bool possible_overwrite);
     506                 :             : 
     507                 :             :     /**
     508                 :             :      * Emplace a coin into cacheCoins without performing any checks, marking
     509                 :             :      * the emplaced coin as dirty.
     510                 :             :      *
     511                 :             :      * NOT FOR GENERAL USE. Used only when loading coins from a UTXO snapshot.
     512                 :             :      * @sa ChainstateManager::PopulateAndValidateSnapshot()
     513                 :             :      */
     514                 :             :     void EmplaceCoinInternalDANGER(const COutPoint& outpoint, Coin&& coin);
     515                 :             : 
     516                 :             :     /**
     517                 :             :      * Spend a coin. Pass moveto in order to get the deleted data.
     518                 :             :      * If no unspent output exists for the passed outpoint, this call
     519                 :             :      * has no effect.
     520                 :             :      */
     521                 :             :     bool SpendCoin(const COutPoint &outpoint, Coin* moveto = nullptr);
     522                 :             : 
     523                 :             :     /**
     524                 :             :      * Push the modifications applied to this cache to its base and wipe local state.
     525                 :             :      * Failure to call this method or Sync() before destruction will cause the changes
     526                 :             :      * to be forgotten.
     527                 :             :      * If reallocate_cache is false, the cache will retain the same memory footprint
     528                 :             :      * after flushing and should be destroyed to deallocate.
     529                 :             :      */
     530                 :             :     virtual void Flush(bool reallocate_cache = true);
     531                 :             : 
     532                 :             :     /**
     533                 :             :      * Push the modifications applied to this cache to its base while retaining
     534                 :             :      * the contents of this cache (except for spent coins, which we erase).
     535                 :             :      * Failure to call this method or Flush() before destruction will cause the changes
     536                 :             :      * to be forgotten.
     537                 :             :      */
     538                 :             :     void Sync();
     539                 :             : 
     540                 :             :     /**
     541                 :             :      * Removes the UTXO with the given outpoint from the cache, if it is
     542                 :             :      * not modified.
     543                 :             :      */
     544                 :             :     void Uncache(const COutPoint &outpoint);
     545                 :             : 
     546                 :             :     //! Size of the cache (in number of transaction outputs)
     547                 :             :     unsigned int GetCacheSize() const;
     548                 :             : 
     549                 :             :     //! Number of dirty cache entries (transaction outputs)
     550 [ +  - ][ +  -  :        3609 :     size_t GetDirtyCount() const noexcept { return m_dirty_count; }
          +  -  +  -  +  
                -  +  - ]
     551                 :             : 
     552                 :             :     //! Calculate the size of the cache (in bytes)
     553                 :             :     size_t DynamicMemoryUsage() const;
     554                 :             : 
     555                 :             :     //! Check whether all prevouts of the transaction are present in the UTXO set represented by this view
     556                 :             :     bool HaveInputs(const CTransaction& tx) const;
     557                 :             : 
     558                 :             :     //! Force a reallocation of the cache map. This is required when downsizing
     559                 :             :     //! the cache because the map's allocator may be hanging onto a lot of
     560                 :             :     //! memory despite having called .clear().
     561                 :             :     //!
     562                 :             :     //! See: https://stackoverflow.com/questions/42114044/how-to-release-unordered-map-memory
     563                 :             :     void ReallocateCache();
     564                 :             : 
     565                 :             :     //! Run an internal sanity check on the cache data structure. */
     566                 :             :     void SanityCheck() const;
     567                 :             : 
     568                 :             :     class ResetGuard
     569                 :             :     {
     570                 :             :     private:
     571                 :             :         friend CCoinsViewCache;
     572                 :             :         CCoinsViewCache& m_cache;
     573                 :      140811 :         explicit ResetGuard(CCoinsViewCache& cache LIFETIMEBOUND) noexcept : m_cache{cache} {}
     574                 :             : 
     575                 :             :     public:
     576                 :             :         ResetGuard(const ResetGuard&) = delete;
     577                 :             :         ResetGuard& operator=(const ResetGuard&) = delete;
     578                 :             :         ResetGuard(ResetGuard&&) = delete;
     579                 :             :         ResetGuard& operator=(ResetGuard&&) = delete;
     580                 :             : 
     581   [ +  -  +  - ]:      140811 :         ~ResetGuard() { m_cache.Reset(); }
                 [ +  - ]
     582                 :             :     };
     583                 :             : 
     584                 :             :     //! Create a scoped guard that will call `Reset()` on this cache when it goes out of scope.
     585         [ +  - ]:      140811 :     [[nodiscard]] ResetGuard CreateResetGuard() noexcept { return ResetGuard{*this}; }
     586                 :             : 
     587                 :             : private:
     588                 :             :     /**
     589                 :             :      * @note this is marked const, but may actually append to `cacheCoins`, increasing
     590                 :             :      * memory usage.
     591                 :             :      */
     592                 :             :     CCoinsMap::iterator FetchCoin(const COutPoint &outpoint) const;
     593                 :             : };
     594                 :             : 
     595                 :             : /**
     596                 :             :  * CCoinsViewCache subclass that asynchronously fetches most block input prevouts in parallel during ConnectBlock without
     597                 :             :  * mutating the base cache.
     598                 :             :  *
     599                 :             :  * Only used in ConnectBlock to pass as an ephemeral view that can be reset if the block is invalid.
     600                 :             :  * It provides the same interface as CCoinsViewCache.
     601                 :             :  * It adds an additional StartFetching method to provide the block.
     602                 :             :  *
     603                 :             :  * When a block is passed to StartFetching, the inputs of the block are flattened into a vector of InputToFetch
     604                 :             :  * objects. StartFetching then submits worker tasks to a ThreadPool and keeps the returned futures alive until fetching
     605                 :             :  * is stopped.
     606                 :             :  *
     607                 :             :  * ProcessInput() atomically fetches and increments m_input_head, so each thread can only access a single element of the
     608                 :             :  * m_inputs vector at a time. Workers race to claim inputs, so they may fetch elements in any order. If the fetched
     609                 :             :  * index is greater than or equal to the size of m_inputs, no more inputs can be fetched and false is returned.
     610                 :             :  *
     611                 :             :  * The worker claims the InputToFetch at this index, fetches the coin from the base cache and moves it into the
     612                 :             :  * InputToFetch object. The ready flag is then set with a release memory order. This allows the ready flag to be
     613                 :             :  * used as a memory fence, guaranteeing the coin being written to the object will have happened before another
     614                 :             :  * thread tests the flag with an acquire memory order.
     615                 :             :  * This assumes all base->PeekCoin() paths are safe for concurrent readers and do not mutate lower cache layers.
     616                 :             :  *
     617                 :             :  * When a coin is requested from the cache on the main thread and is not already in cacheCoins map, FetchCoinFromBase
     618                 :             :  * checks whether the next unconsumed entry in m_inputs has the requested outpoint. On a match, m_input_tail is advanced
     619                 :             :  * and the entry's ready flag is waited on with an acquire memory order until a worker has finished fetching it. The
     620                 :             :  * coin is then moved out and returned. Since the main thread is the only consumer of validation results, it blocks
     621                 :             :  * on the specific input it needs rather than racing workers for other inputs.
     622                 :             :  *
     623                 :             :  * StopFetching() is called in Flush() and in Reset() (the per-block teardown) so workers stop before the block they
     624                 :             :  * reference goes away. It stops fetching by moving m_input_head to the end of m_inputs (so workers quickly exit),
     625                 :             :  * then waits for all futures to complete and clears the per-block state (m_inputs and the head/tail counters).
     626                 :             :  *
     627                 :             :  *       Workers advance m_input_head to fetch inputs. Main thread advances m_input_tail to consume.
     628                 :             :  *
     629                 :             :  *       Before workers start:
     630                 :             :  *
     631                 :             :  *                 m_input_head
     632                 :             :  *                 m_input_tail
     633                 :             :  *                      │
     634                 :             :  *                      ▼
     635                 :             :  *                 ┌─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐
     636                 :             :  *       m_inputs: │ waiting │ waiting │ waiting │ waiting │ waiting │ waiting │ waiting │ waiting │ waiting │
     637                 :             :  *                 │         │         │         │         │         │         │         │         │         │
     638                 :             :  *                 └─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘
     639                 :             :  *
     640                 :             :  *       After workers start:
     641                 :             :  *
     642                 :             :  *                                       Worker 2            Worker 0  Worker 3  Worker 1  m_input_head
     643                 :             :  *                                          │                   │         │         │         │
     644                 :             :  *                                          ▼                   ▼         ▼         ▼         ▼
     645                 :             :  *                 ┌─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐
     646                 :             :  *       m_inputs: │  ready  │  ready  │fetching │  ready  │fetching │fetching │fetching │ waiting │ waiting │
     647                 :             :  *                 │consumed │    ✓    │    ●    │    ✓    │    ●    │    ●    │    ●    │         │         │
     648                 :             :  *                 └─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘
     649                 :             :  *                                ▲
     650                 :             :  *                                │
     651                 :             :  *                           m_input_tail
     652                 :             :  */
     653                 :             : class CoinsViewOverlay : public CCoinsViewCache
     654                 :             : {
     655                 :             : private:
     656                 :             :     //! The latest input not yet being fetched. Workers atomically increment this when fetching.
     657                 :             :     std::atomic_uint32_t m_input_head{0};
     658                 :             :     //! The latest input not yet accessed by a consumer. Only the main thread increments this.
     659                 :             :     mutable uint32_t m_input_tail{0};
     660                 :             : 
     661                 :             :     //! The inputs of the block which is being fetched.
     662                 :       66351 :     struct InputToFetch {
     663                 :             :         //! Workers set this after setting the coin. The main thread tests this before reading the coin.
     664                 :             :         std::atomic_flag ready{};
     665                 :             :         //! The outpoint of the input to fetch.
     666                 :             :         const COutPoint& outpoint;
     667                 :             :         //! The coin that workers will fetch and main thread will insert into cache.
     668                 :             :         //! Mutable so it can be moved in FetchCoinFromBase.
     669                 :             :         mutable std::optional<Coin> coin{std::nullopt};
     670                 :             : 
     671                 :       51703 :         explicit InputToFetch(const COutPoint& o LIFETIMEBOUND) noexcept : outpoint{o} {}
     672                 :             : 
     673                 :             :         //! Move ctor is required for resizing m_inputs in StartFetching. Elements will never move once parallel tasks
     674                 :             :         //! are started, so we can assert that coin is nullopt and ready is false.
     675                 :       14648 :         InputToFetch(InputToFetch&& other) noexcept : outpoint{other.outpoint}
     676                 :             :         {
     677         [ -  + ]:       14648 :             Assert(!other.coin);
     678         [ -  + ]:       14648 :             Assert(!other.ready.test(std::memory_order_relaxed));
     679                 :       14648 :         }
     680                 :             :     };
     681                 :             :     //! Must only be mutated when m_futures is empty. Elements may be mutated when m_futures is not empty.
     682                 :             :     std::vector<InputToFetch> m_inputs{};
     683                 :             : 
     684                 :             :     /**
     685                 :             :      * Claim and fetch the next input in the queue.
     686                 :             :      *
     687                 :             :      * @return true if an input prevout was fetched
     688                 :             :      * @return false if there are no more input prevouts in the queue to fetch
     689                 :             :      */
     690                 :       77278 :     bool ProcessInput() noexcept
     691                 :             :     {
     692         [ -  + ]:       77278 :         const auto i{m_input_head.fetch_add(1, std::memory_order_relaxed)};
     693   [ -  +  +  + ]:       77278 :         if (i >= m_inputs.size()) return false;
     694                 :             : 
     695                 :       51608 :         auto& input{m_inputs[i]};
     696                 :       51608 :         input.coin = base->PeekCoin(input.outpoint);
     697                 :             :         // Use release so writing coin above happens before the main thread acquires.
     698         [ -  + ]:       51608 :         Assert(!input.ready.test_and_set(std::memory_order_release));
     699                 :       51608 :         input.ready.notify_one();
     700                 :       51608 :         return true;
     701                 :             :     }
     702                 :             : 
     703                 :             :     //! Stop all worker threads and clear fetching data.
     704                 :             :     //! Calling this is idempotent, and may safely be called if not fetching.
     705                 :      280249 :     void StopFetching() noexcept
     706                 :             :     {
     707         [ +  + ]:      280249 :         if (m_futures.empty()) {
     708         [ -  + ]:      270947 :             Assert(m_inputs.empty());
     709         [ -  + ]:      270947 :             Assert(m_input_head.load(std::memory_order_relaxed) == 0);
     710         [ -  + ]:      270947 :             Assert(m_input_tail == 0);
     711                 :      270947 :             return;
     712                 :             :         }
     713                 :             :         // Skip fetching the rest of the inputs by moving the head to the end.
     714         [ -  + ]:        9302 :         m_input_head.store(m_inputs.size(), std::memory_order_relaxed);
     715                 :             :         // Wait for all threads to stop.
     716         [ +  + ]:       34972 :         for (auto& future : m_futures) future.wait();
     717                 :        9302 :         m_futures.clear();
     718                 :        9302 :         m_inputs.clear();
     719                 :        9302 :         m_input_head.store(0, std::memory_order_relaxed);
     720                 :        9302 :         m_input_tail = 0;
     721                 :             :     }
     722                 :             : 
     723                 :      500380 :     std::optional<Coin> FetchCoinFromBase(const COutPoint& outpoint) const override
     724                 :             :     {
     725                 :             :         // This assumes ConnectBlock accesses all inputs in the same order as
     726                 :             :         // they are added to m_inputs in StartFetching.
     727   [ -  +  +  +  :      500380 :         if (m_input_tail < m_inputs.size() && m_inputs[m_input_tail].outpoint == outpoint) {
                   +  + ]
     728                 :             :             // We advance the tail since the input is cached and not accessed through this method again.
     729                 :       51510 :             auto& input{m_inputs[m_input_tail++]};
     730                 :             :             // Wait until the coin is ready to be read. We need acquire so we match the worker thread's release.
     731                 :       51510 :             input.ready.wait(/*old=*/false, std::memory_order_acquire);
     732                 :             :             // We can move the coin since we won't access this input again.
     733                 :       51510 :             return std::move(input.coin);
     734                 :             :         }
     735                 :             : 
     736                 :             :         // We will only get here for BIP30 checks, an invalid block, or if the threadpool has not been started.
     737                 :      448870 :         return base->PeekCoin(outpoint);
     738                 :             :     }
     739                 :             : 
     740                 :             :     //! Non-null. May have zero workers when input fetching is disabled.
     741                 :             :     std::shared_ptr<ThreadPool> m_thread_pool;
     742                 :             :     std::vector<std::future<void>> m_futures{};
     743                 :             : 
     744                 :             : protected:
     745                 :      140809 :     void Reset() noexcept override
     746                 :             :     {
     747                 :      140809 :         StopFetching();
     748                 :      140809 :         CCoinsViewCache::Reset();
     749                 :      140809 :     }
     750                 :             : 
     751                 :             : public:
     752                 :        1334 :     explicit CoinsViewOverlay(CCoinsView* in_base, std::shared_ptr<ThreadPool> thread_pool,
     753                 :             :                               bool deterministic = false) noexcept
     754         [ -  + ]:        1334 :         : CCoinsViewCache{in_base, deterministic}, m_thread_pool{std::move(thread_pool)}
     755                 :             :     {
     756         [ -  + ]:        1334 :         Assert(m_thread_pool);
     757                 :        1334 :     }
     758                 :             : 
     759         [ +  - ]:        3993 :     ~CoinsViewOverlay() noexcept override { StopFetching(); }
     760                 :             : 
     761                 :             :     //! Start fetching inputs from block.
     762                 :             :     [[nodiscard]] ResetGuard StartFetching(const CBlock& block LIFETIMEBOUND) noexcept;
     763                 :             : 
     764                 :      138105 :     void Flush(bool reallocate_cache = true) override
     765                 :             :     {
     766                 :      276210 :         if (!Assume(AllInputsConsumed())) {
     767         [ #  # ]:           0 :             LogWarning("Block %s input prevout prefetch queue was not fully consumed; inputs were accessed out of order, so prefetching degraded to serial lookups for this block.", GetBestBlock().ToString());
     768                 :             :         }
     769                 :      138105 :         StopFetching();
     770                 :      138105 :         CCoinsViewCache::Flush(reallocate_cache);
     771                 :      138105 :     }
     772                 :             : 
     773                 :             :     //! Verify that all parallel fetched input prevouts have been consumed.
     774   [ -  +  -  + ]:      138105 :     bool AllInputsConsumed() const noexcept { return m_input_tail == m_inputs.size(); }
     775                 :             : };
     776                 :             : 
     777                 :             : //! Utility function to add all of a transaction's outputs to a cache.
     778                 :             : //! When check is false, this assumes that overwrites are only possible for coinbase transactions.
     779                 :             : //! When check is true, the underlying view may be queried to determine whether an addition is
     780                 :             : //! an overwrite.
     781                 :             : // TODO: pass in a boolean to limit these possible overwrites to known
     782                 :             : // (pre-BIP34) cases.
     783                 :             : void AddCoins(CCoinsViewCache& cache, const CTransaction& tx, int nHeight, bool check = false);
     784                 :             : 
     785                 :             : //! Utility function to find any unspent output with a given txid.
     786                 :             : //! This function can be quite expensive because in the event of a transaction
     787                 :             : //! which is not found in the cache, it can cause up to MAX_OUTPUTS_PER_BLOCK
     788                 :             : //! lookups to database, so it should be used with care.
     789                 :             : const Coin& AccessByTxid(const CCoinsViewCache& cache, const Txid& txid);
     790                 :             : 
     791                 :             : /**
     792                 :             :  * This is a minimally invasive approach to shutdown on LevelDB read errors from the
     793                 :             :  * chainstate, while keeping user interface out of the common library, which is shared
     794                 :             :  * between bitcoind, and bitcoin-qt and non-server tools.
     795                 :             :  *
     796                 :             :  * Writes do not need similar protection, as failure to write is handled by the caller.
     797                 :             : */
     798                 :             : class CCoinsViewErrorCatcher final : public CCoinsViewBacked
     799                 :             : {
     800                 :             : public:
     801         [ +  - ]:        1325 :     explicit CCoinsViewErrorCatcher(CCoinsView* view) : CCoinsViewBacked(view) {}
     802                 :             : 
     803                 :        1099 :     void AddReadErrCallback(std::function<void()> f) {
     804         [ +  - ]:        1099 :         m_err_callbacks.emplace_back(std::move(f));
     805                 :        1099 :     }
     806                 :             : 
     807                 :             :     std::optional<Coin> GetCoin(const COutPoint& outpoint) const override;
     808                 :             :     bool HaveCoin(const COutPoint& outpoint) const override;
     809                 :             :     std::optional<Coin> PeekCoin(const COutPoint& outpoint) const override;
     810                 :             : 
     811                 :             : private:
     812                 :             :     /** A list of callbacks to execute upon leveldb read error. */
     813                 :             :     std::vector<std::function<void()>> m_err_callbacks;
     814                 :             : 
     815                 :             : };
     816                 :             : 
     817                 :             : #endif // BITCOIN_COINS_H
        

Generated by: LCOV version 2.0-1