Coverage Report

Created: 2026-07-20 20:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/tmp/bitcoin/src/coins.h
Line
Count
Source
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 <memusage.h>
13
#include <primitives/transaction.h>
14
#include <primitives/transaction_identifier.h>
15
#include <serialize.h>
16
#include <support/allocators/pool.h>
17
#include <uint256.h>
18
#include <util/check.h>
19
#include <util/log.h>
20
#include <util/overflow.h>
21
#include <util/hasher.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
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
27.1M
    Coin(const CTxOut& outIn, int nHeightIn, bool fCoinBaseIn) : out(outIn), fCoinBase(fCoinBaseIn),nHeight(nHeightIn) {}
60
61
17.3M
    void Clear() {
62
17.3M
        out.SetNull();
63
17.3M
        fCoinBase = false;
64
17.3M
        nHeight = 0;
65
17.3M
    }
66
67
    //! empty constructor
68
78.3M
    Coin() : fCoinBase(false), nHeight(0) { }
69
70
17.7M
    bool IsCoinBase() const {
71
17.7M
        return fCoinBase;
72
17.7M
    }
73
74
    template<typename Stream>
75
298k
    void Serialize(Stream &s) const {
76
298k
        assert(!IsSpent());
77
298k
        uint32_t code{(uint32_t{nHeight} << 1) | uint32_t{fCoinBase}};
78
298k
        ::Serialize(s, VARINT(code));
79
298k
        ::Serialize(s, Using<TxOutCompression>(out));
80
298k
    }
void Coin::Serialize<AutoFile>(AutoFile&) const
Line
Count
Source
75
6.58k
    void Serialize(Stream &s) const {
76
6.58k
        assert(!IsSpent());
77
6.58k
        uint32_t code{(uint32_t{nHeight} << 1) | uint32_t{fCoinBase}};
78
6.58k
        ::Serialize(s, VARINT(code));
79
6.58k
        ::Serialize(s, Using<TxOutCompression>(out));
80
6.58k
    }
void Coin::Serialize<DataStream>(DataStream&) const
Line
Count
Source
75
292k
    void Serialize(Stream &s) const {
76
292k
        assert(!IsSpent());
77
292k
        uint32_t code{(uint32_t{nHeight} << 1) | uint32_t{fCoinBase}};
78
292k
        ::Serialize(s, VARINT(code));
79
292k
        ::Serialize(s, Using<TxOutCompression>(out));
80
292k
    }
81
82
    template<typename Stream>
83
375k
    void Unserialize(Stream &s) {
84
375k
        uint32_t code = 0;
85
375k
        ::Unserialize(s, VARINT(code));
86
375k
        nHeight = code >> 1;
87
375k
        fCoinBase = code & 1;
88
375k
        ::Unserialize(s, Using<TxOutCompression>(out));
89
375k
    }
void Coin::Unserialize<SpanReader>(SpanReader&)
Line
Count
Source
83
97.7k
    void Unserialize(Stream &s) {
84
97.7k
        uint32_t code = 0;
85
97.7k
        ::Unserialize(s, VARINT(code));
86
97.7k
        nHeight = code >> 1;
87
97.7k
        fCoinBase = code & 1;
88
97.7k
        ::Unserialize(s, Using<TxOutCompression>(out));
89
97.7k
    }
void Coin::Unserialize<AutoFile>(AutoFile&)
Line
Count
Source
83
6.35k
    void Unserialize(Stream &s) {
84
6.35k
        uint32_t code = 0;
85
6.35k
        ::Unserialize(s, VARINT(code));
86
6.35k
        nHeight = code >> 1;
87
6.35k
        fCoinBase = code & 1;
88
6.35k
        ::Unserialize(s, Using<TxOutCompression>(out));
89
6.35k
    }
void Coin::Unserialize<DataStream>(DataStream&)
Line
Count
Source
83
271k
    void Unserialize(Stream &s) {
84
271k
        uint32_t code = 0;
85
271k
        ::Unserialize(s, VARINT(code));
86
271k
        nHeight = code >> 1;
87
271k
        fCoinBase = code & 1;
88
271k
        ::Unserialize(s, Using<TxOutCompression>(out));
89
271k
    }
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
158M
    bool IsSpent() const {
95
158M
        return out.IsNull();
96
158M
    }
97
98
64.2M
    size_t DynamicMemoryUsage() const {
99
64.2M
        return memusage::DynamicUsage(out.scriptPubKey);
100
64.2M
    }
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
    static void AddFlags(uint8_t flags, CoinsCachePair& pair, CoinsCachePair& sentinel) noexcept
139
71.4M
    {
140
71.4M
        Assume(flags & (DIRTY | FRESH));
141
71.4M
        if (!pair.second.m_flags) {
142
44.5M
            Assume(!pair.second.m_prev && !pair.second.m_next);
143
44.5M
            pair.second.m_prev = sentinel.second.m_prev;
144
44.5M
            pair.second.m_next = &sentinel;
145
44.5M
            sentinel.second.m_prev = &pair;
146
44.5M
            pair.second.m_prev->second.m_next = &pair;
147
44.5M
        }
148
71.4M
        Assume(pair.second.m_prev && pair.second.m_next);
149
71.4M
        pair.second.m_flags |= flags;
150
71.4M
    }
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
71.5M
    CCoinsCacheEntry() noexcept = default;
177
25.1k
    explicit CCoinsCacheEntry(Coin&& coin_) noexcept : coin(std::move(coin_)) {}
178
    ~CCoinsCacheEntry()
179
71.6M
    {
180
71.6M
        SetClean();
181
71.6M
    }
182
183
44.5M
    static void SetDirty(CoinsCachePair& pair, CoinsCachePair& sentinel) noexcept { AddFlags(DIRTY, pair, sentinel); }
184
26.8M
    static void SetFresh(CoinsCachePair& pair, CoinsCachePair& sentinel) noexcept { AddFlags(FRESH, pair, sentinel); }
185
186
    void SetClean() noexcept
187
71.6M
    {
188
71.6M
        if (!m_flags) return;
189
44.9M
        m_next->second.m_prev = m_prev;
190
44.9M
        m_prev->second.m_next = m_next;
191
44.9M
        m_flags = 0;
192
44.9M
        m_prev = m_next = nullptr;
193
44.9M
    }
194
47.2M
    bool IsDirty() const noexcept { return m_flags & DIRTY; }
195
19.0M
    bool IsFresh() const noexcept { return m_flags & FRESH; }
196
197
    //! Only call Next when this entry is DIRTY, FRESH, or both
198
    CoinsCachePair* Next() const noexcept
199
1.22M
    {
200
1.22M
        Assume(m_flags);
201
1.22M
        return m_next;
202
1.22M
    }
203
204
    //! Only call Prev when this entry is DIRTY, FRESH, or both
205
    CoinsCachePair* Prev() const noexcept
206
111k
    {
207
111k
        Assume(m_flags);
208
111k
        return m_prev;
209
111k
    }
210
211
    //! Only use this for initializing the linked list sentinel
212
    void SelfRef(CoinsCachePair& pair) noexcept
213
404k
    {
214
404k
        Assume(&pair.second == this);
215
404k
        m_prev = &pair;
216
404k
        m_next = &pair;
217
        // Set sentinel to DIRTY so we can call Next on it
218
404k
        m_flags = DIRTY;
219
404k
    }
220
};
221
222
/**
223
 * PoolAllocator's MAX_BLOCK_SIZE_BYTES parameter here uses sizeof the data, and adds the size
224
 * of 4 pointers. We do not know the exact node size used in the std::unordered_node implementation
225
 * because it is implementation defined. Most implementations have an overhead of 1 or 2 pointers,
226
 * so nodes can be connected in a linked list, and in some cases the hash value is stored as well.
227
 * Using an additional sizeof(void*)*4 for MAX_BLOCK_SIZE_BYTES should thus be sufficient so that
228
 * all implementations can allocate the nodes from the PoolAllocator.
229
 */
230
using CCoinsMap = std::unordered_map<COutPoint,
231
                                     CCoinsCacheEntry,
232
                                     SaltedOutpointHasher,
233
                                     std::equal_to<COutPoint>,
234
                                     PoolAllocator<CoinsCachePair,
235
                                                   sizeof(CoinsCachePair) + sizeof(void*) * 4>>;
236
237
using CCoinsMapMemoryResource = CCoinsMap::allocator_type::ResourceType;
238
239
/** Cursor for iterating over CoinsView state */
240
class CCoinsViewCursor
241
{
242
public:
243
1.25k
    CCoinsViewCursor(const uint256& in_block_hash) : block_hash(in_block_hash) {}
244
1.25k
    virtual ~CCoinsViewCursor() = default;
245
246
    virtual bool GetKey(COutPoint &key) const = 0;
247
    virtual bool GetValue(Coin &coin) const = 0;
248
249
    virtual bool Valid() const = 0;
250
    virtual void Next() = 0;
251
252
    //! Get best block at the time this cursor was created
253
102
    const uint256& GetBestBlock() const { return block_hash; }
254
private:
255
    uint256 block_hash;
256
};
257
258
/**
259
 * Cursor for iterating over the linked list of flagged entries in CCoinsViewCache.
260
 *
261
 * This is a helper struct to encapsulate the diverging logic between a non-erasing
262
 * CCoinsViewCache::Sync and an erasing CCoinsViewCache::Flush. This allows the receiver
263
 * of CCoinsView::BatchWrite to iterate through the flagged entries without knowing
264
 * the caller's intent.
265
 *
266
 * However, the receiver can still call CoinsViewCacheCursor::WillErase to see if the
267
 * caller will erase the entry after BatchWrite returns. If so, the receiver can
268
 * perform optimizations such as moving the coin out of the CCoinsCachEntry instead
269
 * of copying it.
270
 */
271
struct CoinsViewCacheCursor
272
{
273
    //! If will_erase is not set, iterating through the cursor will erase spent coins from the map,
274
    //! and other coins will be unflagged (removing them from the linked list).
275
    //! If will_erase is set, the underlying map and linked list will not be modified,
276
    //! as the caller is expected to wipe the entire map anyway.
277
    //! This is an optimization compared to erasing all entries as the cursor iterates them when will_erase is set.
278
    //! Calling CCoinsMap::clear() afterwards is faster because a CoinsCachePair cannot be coerced back into a
279
    //! CCoinsMap::iterator to be erased, and must therefore be looked up again by key in the CCoinsMap before being erased.
280
    CoinsViewCacheCursor(size_t& dirty_count LIFETIMEBOUND,
281
                         CoinsCachePair& sentinel LIFETIMEBOUND,
282
                         CCoinsMap& map LIFETIMEBOUND,
283
                         bool will_erase) noexcept
284
131k
        : m_dirty_count(dirty_count), m_sentinel(sentinel), m_map(map), m_will_erase(will_erase) {}
285
286
131k
    inline CoinsCachePair* Begin() const noexcept { return m_sentinel.second.Next(); }
287
1.05M
    inline CoinsCachePair* End() const noexcept { return &m_sentinel; }
288
289
    //! Return the next entry after current, possibly erasing current
290
    inline CoinsCachePair* NextAndMaybeErase(CoinsCachePair& current) noexcept
291
926k
    {
292
926k
        const auto next_entry{current.second.Next()};
293
926k
        Assume(TrySub(m_dirty_count, current.second.IsDirty()));
294
        // If we are not going to erase the cache, we must still erase spent entries.
295
        // Otherwise, clear the state of the entry.
296
926k
        if (!m_will_erase) {
297
80.9k
            if (current.second.coin.IsSpent()) {
298
21.2k
                assert(current.second.coin.DynamicMemoryUsage() == 0); // scriptPubKey was already cleared in SpendCoin
299
21.2k
                m_map.erase(current.first);
300
59.6k
            } else {
301
59.6k
                current.second.SetClean();
302
59.6k
            }
303
80.9k
        }
304
926k
        return next_entry;
305
926k
    }
306
307
476k
    inline bool WillErase(CoinsCachePair& current) const noexcept { return m_will_erase || current.second.coin.IsSpent(); }
308
3.77k
    size_t GetDirtyCount() const noexcept { return m_dirty_count; }
309
3.77k
    size_t GetTotalCount() const noexcept { return m_map.size(); }
310
private:
311
    size_t& m_dirty_count;
312
    CoinsCachePair& m_sentinel;
313
    CCoinsMap& m_map;
314
    bool m_will_erase;
315
};
316
317
/** Pure abstract view on the open txout dataset. */
318
class CCoinsView
319
{
320
public:
321
    //! As we use CCoinsViews polymorphically, have a virtual destructor
322
459k
    virtual ~CCoinsView() = default;
323
324
    //! Retrieve the Coin (unspent transaction output) for a given outpoint.
325
    //! May populate the cache. Use PeekCoin() to perform a non-caching lookup.
326
    virtual std::optional<Coin> GetCoin(const COutPoint& outpoint) const = 0;
327
328
    //! Retrieve the Coin (unspent transaction output) for a given outpoint, without caching results.
329
    //! Does not populate the cache. Use GetCoin() to cache the result.
330
    virtual std::optional<Coin> PeekCoin(const COutPoint& outpoint) const = 0;
331
332
    //! Just check whether a given outpoint is unspent.
333
    //! May populate the cache. Use PeekCoin() to perform a non-caching lookup.
334
    virtual bool HaveCoin(const COutPoint& outpoint) const = 0;
335
336
    //! Retrieve the block hash whose state this CCoinsView currently represents
337
    virtual uint256 GetBestBlock() const = 0;
338
339
    //! Retrieve the range of blocks that may have been only partially written.
340
    //! If the database is in a consistent state, the result is the empty vector.
341
    //! Otherwise, a two-element vector is returned consisting of the new and
342
    //! the old block hash, in that order.
343
    virtual std::vector<uint256> GetHeadBlocks() const = 0;
344
345
    //! Do a bulk modification (multiple Coin changes + BestBlock change).
346
    //! The passed cursor is used to iterate through the coins.
347
    virtual void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& block_hash) = 0;
348
349
    //! Estimate database size
350
    virtual size_t EstimateSize() const = 0;
351
};
352
353
/** Noop coins view. */
354
class CoinsViewEmpty : public CCoinsView
355
{
356
protected:
357
4
    CoinsViewEmpty() = default;
358
359
public:
360
    static CoinsViewEmpty& Get();
361
362
    CoinsViewEmpty(const CoinsViewEmpty&) = delete;
363
    CoinsViewEmpty& operator=(const CoinsViewEmpty&) = delete;
364
365
29
    std::optional<Coin> GetCoin(const COutPoint&) const override { return {}; }
366
1
    std::optional<Coin> PeekCoin(const COutPoint& outpoint) const override { return GetCoin(outpoint); }
367
0
    bool HaveCoin(const COutPoint& outpoint) const override { return !!GetCoin(outpoint); }
368
0
    uint256 GetBestBlock() const override { return {}; }
369
0
    std::vector<uint256> GetHeadBlocks() const override { return {}; }
370
    void BatchWrite(CoinsViewCacheCursor& cursor, const uint256&) override
371
0
    {
372
0
        for (auto it{cursor.Begin()}; it != cursor.End(); it = cursor.NextAndMaybeErase(*it)) { }
373
0
    }
374
0
    size_t EstimateSize() const override { return 0; }
375
};
376
377
/** CCoinsView backed by another CCoinsView */
378
class CCoinsViewBacked : public CCoinsView
379
{
380
protected:
381
    CCoinsView* base;
382
383
public:
384
458k
    explicit CCoinsViewBacked(CCoinsView* in_view) : base{Assert(in_view)} {}
385
386
91.1k
    void SetBackend(CCoinsView& in_view) { base = &in_view; }
387
388
918k
    std::optional<Coin> GetCoin(const COutPoint& outpoint) const override { return base->GetCoin(outpoint); }
389
404k
    std::optional<Coin> PeekCoin(const COutPoint& outpoint) const override { return base->PeekCoin(outpoint); }
390
0
    bool HaveCoin(const COutPoint& outpoint) const override { return base->HaveCoin(outpoint); }
391
46.3k
    uint256 GetBestBlock() const override { return base->GetBestBlock(); }
392
0
    std::vector<uint256> GetHeadBlocks() const override { return base->GetHeadBlocks(); }
393
3.46k
    void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& block_hash) override { base->BatchWrite(cursor, block_hash); }
394
0
    size_t EstimateSize() const override { return base->EstimateSize(); }
395
};
396
397
398
/** CCoinsView that adds a memory cache for transactions to another CCoinsView */
399
class CCoinsViewCache : public CCoinsViewBacked
400
{
401
private:
402
    const bool m_deterministic;
403
404
protected:
405
    /**
406
     * Make mutable so that we can "fill the cache" even from Get-methods
407
     * declared as "const".
408
     */
409
    mutable uint256 m_block_hash;
410
    mutable CCoinsMapMemoryResource m_cache_coins_memory_resource{};
411
    /* The starting sentinel of the flagged entry circular doubly linked list. */
412
    mutable CoinsCachePair m_sentinel;
413
    mutable CCoinsMap cacheCoins;
414
415
    /* Cached dynamic memory usage for the inner Coin objects. */
416
    mutable size_t cachedCoinsUsage{0};
417
    /* Running count of dirty Coin cache entries. */
418
    mutable size_t m_dirty_count{0};
419
420
    /**
421
     * Discard all modifications made to this cache without flushing to the base view.
422
     * This can be used to efficiently reuse a cache instance across multiple operations.
423
     */
424
    virtual void Reset() noexcept;
425
426
    /* Fetch the coin from base. Used for cache misses in FetchCoin. */
427
    virtual std::optional<Coin> FetchCoinFromBase(const COutPoint& outpoint) const;
428
429
public:
430
    CCoinsViewCache(CCoinsView* in_base, bool deterministic = false);
431
432
    /**
433
     * By deleting the copy constructor, we prevent accidentally using it when one intends to create a cache on top of a base cache.
434
     */
435
    CCoinsViewCache(const CCoinsViewCache &) = delete;
436
437
    // Standard CCoinsView methods
438
    std::optional<Coin> GetCoin(const COutPoint& outpoint) const override;
439
    std::optional<Coin> PeekCoin(const COutPoint& outpoint) const override;
440
    bool HaveCoin(const COutPoint& outpoint) const override;
441
    uint256 GetBestBlock() const override;
442
    void SetBestBlock(const uint256& block_hash);
443
    void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& block_hash) override;
444
445
    /**
446
     * Check if we have the given utxo already loaded in this cache.
447
     * The semantics are the same as HaveCoin(), but no calls to
448
     * the backing CCoinsView are made.
449
     */
450
    bool HaveCoinInCache(const COutPoint &outpoint) const;
451
452
    /**
453
     * Return a reference to Coin in the cache, or coinEmpty if not found. This is
454
     * more efficient than GetCoin.
455
     *
456
     * Generally, do not hold the reference returned for more than a short scope.
457
     * While the current implementation allows for modifications to the contents
458
     * of the cache while holding the reference, this behavior should not be relied
459
     * on! To be safe, best to not hold the returned reference through any other
460
     * calls to this cache.
461
     */
462
    const Coin& AccessCoin(const COutPoint &output) const;
463
464
    /**
465
     * Add a coin. Set possible_overwrite to true if an unspent version may
466
     * already exist in the cache.
467
     */
468
    void AddCoin(const COutPoint& outpoint, Coin&& coin, bool possible_overwrite);
469
470
    /**
471
     * Emplace a coin into cacheCoins without performing any checks, marking
472
     * the emplaced coin as dirty.
473
     *
474
     * NOT FOR GENERAL USE. Used only when loading coins from a UTXO snapshot.
475
     * @sa ChainstateManager::PopulateAndValidateSnapshot()
476
     */
477
    void EmplaceCoinInternalDANGER(const COutPoint& outpoint, Coin&& coin);
478
479
    /**
480
     * Spend a coin. Pass moveto in order to get the deleted data.
481
     * If no unspent output exists for the passed outpoint, this call
482
     * has no effect.
483
     */
484
    bool SpendCoin(const COutPoint &outpoint, Coin* moveto = nullptr);
485
486
    /**
487
     * Push the modifications applied to this cache to its base and wipe local state.
488
     * Failure to call this method or Sync() before destruction will cause the changes
489
     * to be forgotten.
490
     * If reallocate_cache is false, the cache will retain the same memory footprint
491
     * after flushing and should be destroyed to deallocate.
492
     */
493
    virtual void Flush(bool reallocate_cache = true);
494
495
    /**
496
     * Push the modifications applied to this cache to its base while retaining
497
     * the contents of this cache (except for spent coins, which we erase).
498
     * Failure to call this method or Flush() before destruction will cause the changes
499
     * to be forgotten.
500
     */
501
    void Sync();
502
503
    /**
504
     * Removes the UTXO with the given outpoint from the cache, if it is
505
     * not modified.
506
     */
507
    void Uncache(const COutPoint &outpoint);
508
509
    //! Size of the cache (in number of transaction outputs)
510
    unsigned int GetCacheSize() const;
511
512
    //! Number of dirty cache entries (transaction outputs)
513
3.44k
    size_t GetDirtyCount() const noexcept { return m_dirty_count; }
514
515
    //! Calculate the size of the cache (in bytes)
516
    size_t DynamicMemoryUsage() const;
517
518
    //! Check whether all prevouts of the transaction are present in the UTXO set represented by this view
519
    bool HaveInputs(const CTransaction& tx) const;
520
521
    //! Force a reallocation of the cache map. This is required when downsizing
522
    //! the cache because the map's allocator may be hanging onto a lot of
523
    //! memory despite having called .clear().
524
    //!
525
    //! See: https://stackoverflow.com/questions/42114044/how-to-release-unordered-map-memory
526
    void ReallocateCache();
527
528
    //! Run an internal sanity check on the cache data structure. */
529
    void SanityCheck() const;
530
531
    class ResetGuard
532
    {
533
    private:
534
        friend CCoinsViewCache;
535
        CCoinsViewCache& m_cache;
536
114k
        explicit ResetGuard(CCoinsViewCache& cache LIFETIMEBOUND) noexcept : m_cache{cache} {}
537
538
    public:
539
        ResetGuard(const ResetGuard&) = delete;
540
        ResetGuard& operator=(const ResetGuard&) = delete;
541
        ResetGuard(ResetGuard&&) = delete;
542
        ResetGuard& operator=(ResetGuard&&) = delete;
543
544
114k
        ~ResetGuard() { m_cache.Reset(); }
545
    };
546
547
    //! Create a scoped guard that will call `Reset()` on this cache when it goes out of scope.
548
114k
    [[nodiscard]] ResetGuard CreateResetGuard() noexcept { return ResetGuard{*this}; }
549
550
private:
551
    /**
552
     * @note this is marked const, but may actually append to `cacheCoins`, increasing
553
     * memory usage.
554
     */
555
    CCoinsMap::iterator FetchCoin(const COutPoint &outpoint) const;
556
};
557
558
/**
559
 * CCoinsViewCache subclass that asynchronously fetches most block input prevouts in parallel during ConnectBlock without
560
 * mutating the base cache.
561
 *
562
 * Only used in ConnectBlock to pass as an ephemeral view that can be reset if the block is invalid.
563
 * It provides the same interface as CCoinsViewCache.
564
 * It adds an additional StartFetching method to provide the block.
565
 *
566
 * When a block is passed to StartFetching, the inputs of the block are flattened into a vector of InputToFetch
567
 * objects. StartFetching then submits worker tasks to a ThreadPool and keeps the returned futures alive until fetching
568
 * is stopped.
569
 *
570
 * ProcessInput() atomically fetches and increments m_input_head, so each thread can only access a single element of the
571
 * m_inputs vector at a time. Workers race to claim inputs, so they may fetch elements in any order. If the fetched
572
 * index is greater than or equal to the size of m_inputs, no more inputs can be fetched and false is returned.
573
 *
574
 * The worker claims the InputToFetch at this index, fetches the coin from the base cache and moves it into the
575
 * InputToFetch object. The ready flag is then set with a release memory order. This allows the ready flag to be
576
 * used as a memory fence, guaranteeing the coin being written to the object will have happened before another
577
 * thread tests the flag with an acquire memory order.
578
 * This assumes all base->PeekCoin() paths are safe for concurrent readers and do not mutate lower cache layers.
579
 *
580
 * When a coin is requested from the cache on the main thread and is not already in cacheCoins map, FetchCoinFromBase
581
 * checks whether the next unconsumed entry in m_inputs has the requested outpoint. On a match, m_input_tail is advanced
582
 * and the entry's ready flag is waited on with an acquire memory order until a worker has finished fetching it. The
583
 * coin is then moved out and returned. Since the main thread is the only consumer of validation results, it blocks
584
 * on the specific input it needs rather than racing workers for other inputs.
585
 *
586
 * StopFetching() is called in Flush() and in Reset() (the per-block teardown) so workers stop before the block they
587
 * reference goes away. It stops fetching by moving m_input_head to the end of m_inputs (so workers quickly exit),
588
 * then waits for all futures to complete and clears the per-block state (m_inputs and the head/tail counters).
589
 *
590
 *       Workers advance m_input_head to fetch inputs. Main thread advances m_input_tail to consume.
591
 *
592
 *       Before workers start:
593
 *
594
 *                 m_input_head
595
 *                 m_input_tail
596
 *                      │
597
 *                      ▼
598
 *                 ┌─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐
599
 *       m_inputs: │ waiting │ waiting │ waiting │ waiting │ waiting │ waiting │ waiting │ waiting │ waiting │
600
 *                 │         │         │         │         │         │         │         │         │         │
601
 *                 └─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘
602
 *
603
 *       After workers start:
604
 *
605
 *                                       Worker 2            Worker 0  Worker 3  Worker 1  m_input_head
606
 *                                          │                   │         │         │         │
607
 *                                          ▼                   ▼         ▼         ▼         ▼
608
 *                 ┌─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐
609
 *       m_inputs: │  ready  │  ready  │fetching │  ready  │fetching │fetching │fetching │ waiting │ waiting │
610
 *                 │consumed │    ✓    │    ●    │    ✓    │    ●    │    ●    │    ●    │         │         │
611
 *                 └─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘
612
 *                                ▲
613
 *                                │
614
 *                           m_input_tail
615
 */
616
class CoinsViewOverlay : public CCoinsViewCache
617
{
618
private:
619
    //! The latest input not yet being fetched. Workers atomically increment this when fetching.
620
    std::atomic_uint32_t m_input_head{0};
621
    //! The latest input not yet accessed by a consumer. Only the main thread increments this.
622
    mutable uint32_t m_input_tail{0};
623
624
    //! The inputs of the block which is being fetched.
625
    struct InputToFetch {
626
        //! Workers set this after setting the coin. The main thread tests this before reading the coin.
627
        std::atomic_flag ready{};
628
        //! The outpoint of the input to fetch.
629
        const COutPoint& outpoint;
630
        //! The coin that workers will fetch and main thread will insert into cache.
631
        //! Mutable so it can be moved in FetchCoinFromBase.
632
        mutable std::optional<Coin> coin{std::nullopt};
633
634
55.3k
        explicit InputToFetch(const COutPoint& o LIFETIMEBOUND) noexcept : outpoint{o} {}
635
636
        //! Move ctor is required for resizing m_inputs in StartFetching. Elements will never move once parallel tasks
637
        //! are started, so we can assert that coin is nullopt and ready is false.
638
14.5k
        InputToFetch(InputToFetch&& other) noexcept : outpoint{other.outpoint}
639
14.5k
        {
640
14.5k
            Assert(!other.coin);
641
14.5k
            Assert(!other.ready.test(std::memory_order_relaxed));
642
14.5k
        }
643
    };
644
    //! Must only be mutated when m_futures is empty. Elements may be mutated when m_futures is not empty.
645
    std::vector<InputToFetch> m_inputs{};
646
647
    /**
648
     * Claim and fetch the next input in the queue.
649
     *
650
     * @return true if an input prevout was fetched
651
     * @return false if there are no more input prevouts in the queue to fetch
652
     */
653
    bool ProcessInput() noexcept
654
80.4k
    {
655
80.4k
        const auto i{m_input_head.fetch_add(1, std::memory_order_relaxed)};
656
80.4k
        if (i >= m_inputs.size()) return false;
657
658
55.1k
        auto& input{m_inputs[i]};
659
55.1k
        input.coin = base->PeekCoin(input.outpoint);
660
        // Use release so writing coin above happens before the main thread acquires.
661
55.1k
        Assert(!input.ready.test_and_set(std::memory_order_release));
662
55.1k
        input.ready.notify_one();
663
55.1k
        return true;
664
80.4k
    }
665
666
    //! Stop all worker threads and clear fetching data.
667
    //! Calling this is idempotent, and may safely be called if not fetching.
668
    void StopFetching() noexcept
669
228k
    {
670
228k
        if (m_futures.empty()) {
671
219k
            Assert(m_inputs.empty());
672
219k
            Assert(m_input_head.load(std::memory_order_relaxed) == 0);
673
219k
            Assert(m_input_tail == 0);
674
219k
            return;
675
219k
        }
676
        // Skip fetching the rest of the inputs by moving the head to the end.
677
9.23k
        m_input_head.store(m_inputs.size(), std::memory_order_relaxed);
678
        // Wait for all threads to stop.
679
25.2k
        for (auto& future : m_futures) future.wait();
680
9.23k
        m_futures.clear();
681
9.23k
        m_inputs.clear();
682
9.23k
        m_input_head.store(0, std::memory_order_relaxed);
683
9.23k
        m_input_tail = 0;
684
9.23k
    }
685
686
    std::optional<Coin> FetchCoinFromBase(const COutPoint& outpoint) const override
687
463k
    {
688
        // This assumes ConnectBlock accesses all inputs in the same order as
689
        // they are added to m_inputs in StartFetching.
690
463k
        if (m_input_tail < m_inputs.size() && m_inputs[m_input_tail].outpoint == outpoint) {
691
            // We advance the tail since the input is cached and not accessed through this method again.
692
55.1k
            auto& input{m_inputs[m_input_tail++]};
693
            // Wait until the coin is ready to be read. We need acquire so we match the worker thread's release.
694
55.1k
            input.ready.wait(/*old=*/false, std::memory_order_acquire);
695
            // We can move the coin since we won't access this input again.
696
55.1k
            return std::move(input.coin);
697
55.1k
        }
698
699
        // We will only get here for BIP30 checks, an invalid block, or if the threadpool has not been started.
700
408k
        return base->PeekCoin(outpoint);
701
463k
    }
702
703
    //! Non-null. May have zero workers when input fetching is disabled.
704
    std::shared_ptr<ThreadPool> m_thread_pool;
705
    std::vector<std::future<void>> m_futures{};
706
707
protected:
708
    void Reset() noexcept override
709
114k
    {
710
114k
        StopFetching();
711
114k
        CCoinsViewCache::Reset();
712
114k
    }
713
714
public:
715
    explicit CoinsViewOverlay(CCoinsView* in_base, std::shared_ptr<ThreadPool> thread_pool,
716
                              bool deterministic = false) noexcept
717
1.26k
        : CCoinsViewCache{in_base, deterministic}, m_thread_pool{std::move(thread_pool)}
718
1.26k
    {
719
1.26k
        Assert(m_thread_pool);
720
1.26k
    }
721
722
1.26k
    ~CoinsViewOverlay() noexcept override { StopFetching(); }
723
724
    //! Start fetching inputs from block.
725
    [[nodiscard]] ResetGuard StartFetching(const CBlock& block LIFETIMEBOUND) noexcept;
726
727
    void Flush(bool reallocate_cache = true) override
728
112k
    {
729
112k
        if (!Assume(AllInputsConsumed())) {
730
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());
731
0
        }
732
112k
        StopFetching();
733
112k
        CCoinsViewCache::Flush(reallocate_cache);
734
112k
    }
735
736
    //! Verify that all parallel fetched input prevouts have been consumed.
737
112k
    bool AllInputsConsumed() const noexcept { return m_input_tail == m_inputs.size(); }
738
};
739
740
//! Utility function to add all of a transaction's outputs to a cache.
741
//! When check is false, this assumes that overwrites are only possible for coinbase transactions.
742
//! When check is true, the underlying view may be queried to determine whether an addition is
743
//! an overwrite.
744
// TODO: pass in a boolean to limit these possible overwrites to known
745
// (pre-BIP34) cases.
746
void AddCoins(CCoinsViewCache& cache, const CTransaction& tx, int nHeight, bool check = false);
747
748
//! Utility function to find any unspent output with a given txid.
749
//! This function can be quite expensive because in the event of a transaction
750
//! which is not found in the cache, it can cause up to MAX_OUTPUTS_PER_BLOCK
751
//! lookups to database, so it should be used with care.
752
const Coin& AccessByTxid(const CCoinsViewCache& cache, const Txid& txid);
753
754
/**
755
 * This is a minimally invasive approach to shutdown on LevelDB read errors from the
756
 * chainstate, while keeping user interface out of the common library, which is shared
757
 * between bitcoind, and bitcoin-qt and non-server tools.
758
 *
759
 * Writes do not need similar protection, as failure to write is handled by the caller.
760
*/
761
class CCoinsViewErrorCatcher final : public CCoinsViewBacked
762
{
763
public:
764
1.25k
    explicit CCoinsViewErrorCatcher(CCoinsView* view) : CCoinsViewBacked(view) {}
765
766
1.04k
    void AddReadErrCallback(std::function<void()> f) {
767
1.04k
        m_err_callbacks.emplace_back(std::move(f));
768
1.04k
    }
769
770
    std::optional<Coin> GetCoin(const COutPoint& outpoint) const override;
771
    bool HaveCoin(const COutPoint& outpoint) const override;
772
    std::optional<Coin> PeekCoin(const COutPoint& outpoint) const override;
773
774
private:
775
    /** A list of callbacks to execute upon leveldb read error. */
776
    std::vector<std::function<void()>> m_err_callbacks;
777
778
};
779
780
#endif // BITCOIN_COINS_H