LCOV - code coverage report
Current view: top level - src/test/fuzz - coins_view.cpp (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 99.1 % 232 230
Test Date: 2026-04-19 06:20:48 Functions: 100.0 % 29 29
Branches: 70.6 % 286 202

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2020-present The Bitcoin Core developers
       2                 :             : // Distributed under the MIT software license, see the accompanying
       3                 :             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4                 :             : 
       5                 :             : #include <coins.h>
       6                 :             : #include <consensus/amount.h>
       7                 :             : #include <consensus/tx_check.h>
       8                 :             : #include <consensus/tx_verify.h>
       9                 :             : #include <consensus/validation.h>
      10                 :             : #include <policy/policy.h>
      11                 :             : #include <primitives/transaction.h>
      12                 :             : #include <script/interpreter.h>
      13                 :             : #include <test/fuzz/FuzzedDataProvider.h>
      14                 :             : #include <test/fuzz/fuzz.h>
      15                 :             : #include <test/fuzz/util.h>
      16                 :             : #include <test/util/setup_common.h>
      17                 :             : #include <txdb.h>
      18                 :             : #include <util/hasher.h>
      19                 :             : 
      20                 :             : #include <cassert>
      21                 :             : #include <algorithm>
      22                 :             : #include <cstdint>
      23                 :             : #include <functional>
      24                 :             : #include <limits>
      25                 :             : #include <memory>
      26                 :             : #include <optional>
      27                 :             : #include <ranges>
      28                 :             : #include <stdexcept>
      29                 :             : #include <string>
      30                 :             : #include <utility>
      31                 :             : #include <vector>
      32                 :             : 
      33                 :             : namespace {
      34                 :             : const Coin EMPTY_COIN{};
      35                 :             : 
      36                 :       40670 : bool operator==(const Coin& a, const Coin& b)
      37                 :             : {
      38   [ +  +  -  + ]:       40670 :     if (a.IsSpent() && b.IsSpent()) return true;
      39   [ +  +  +  +  :       36284 :     return a.fCoinBase == b.fCoinBase && a.nHeight == b.nHeight && a.out == b.out;
                   +  + ]
      40                 :             : }
      41                 :             : 
      42                 :             : /**
      43                 :             :  * MutationGuardCoinsViewCache asserts that nothing mutates cacheCoins until
      44                 :             :  * BatchWrite is called. It keeps a snapshot of the cacheCoins state, which it
      45                 :             :  * uses for the assertion in BatchWrite. After the call to the superclass
      46                 :             :  * CCoinsViewCache::BatchWrite returns, it recomputes the snapshot at that
      47                 :             :  * moment.
      48                 :             :  */
      49                 :             : class MutationGuardCoinsViewCache final : public CCoinsViewCache
      50                 :             : {
      51                 :             : private:
      52         [ -  - ]:      109266 :     struct CacheCoinSnapshot {
      53                 :       27095 :         COutPoint outpoint;
      54                 :       27095 :         bool dirty{false};
      55                 :       27095 :         bool fresh{false};
      56                 :       27095 :         Coin coin;
      57   [ +  -  +  -  :       27095 :         bool operator==(const CacheCoinSnapshot&) const = default;
             +  -  -  + ]
      58                 :             :     };
      59                 :             : 
      60                 :       59694 :     std::vector<CacheCoinSnapshot> ComputeCacheCoinsSnapshot() const
      61                 :             :     {
      62                 :       59694 :         std::vector<CacheCoinSnapshot> snapshot;
      63         [ +  - ]:       59694 :         snapshot.reserve(cacheCoins.size());
      64                 :             : 
      65   [ +  +  +  - ]:      115415 :         for (const auto& [outpoint, entry] : cacheCoins) {
      66         [ +  - ]:       55721 :             snapshot.emplace_back(outpoint, entry.IsDirty(), entry.IsFresh(), entry.coin);
      67                 :             :         }
      68                 :             : 
      69                 :       59694 :         std::ranges::sort(snapshot, std::less<>{}, &CacheCoinSnapshot::outpoint);
      70                 :       59694 :         return snapshot;
      71                 :           0 :     }
      72                 :             : 
      73                 :             :     mutable std::vector<CacheCoinSnapshot> m_expected_snapshot{ComputeCacheCoinsSnapshot()};
      74                 :             : 
      75                 :             : public:
      76                 :       29024 :     void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& block_hash) override
      77                 :             :     {
      78                 :             :         // Nothing must modify cacheCoins other than BatchWrite.
      79         [ -  + ]:       29024 :         assert(ComputeCacheCoinsSnapshot() == m_expected_snapshot);
      80                 :       29024 :         CCoinsViewCache::BatchWrite(cursor, block_hash);
      81                 :       29024 :         m_expected_snapshot = ComputeCacheCoinsSnapshot();
      82                 :       29024 :     }
      83                 :             : 
      84                 :             :     using CCoinsViewCache::CCoinsViewCache;
      85                 :             : };
      86                 :             : } // namespace
      87                 :             : 
      88                 :           3 : void initialize_coins_view()
      89                 :             : {
      90   [ +  -  +  -  :           3 :     static const auto testing_setup = MakeNoLogFileContext<>();
                   +  - ]
      91                 :           3 : }
      92                 :             : 
      93                 :        7985 : void TestCoinsView(FuzzedDataProvider& fuzzed_data_provider, CCoinsViewCache& coins_view_cache, CCoinsView* backend_coins_view)
      94                 :             : {
      95         [ +  - ]:        7985 :     const bool is_db{dynamic_cast<CCoinsViewDB*>(backend_coins_view) != nullptr};
      96                 :        7985 :     bool good_data{true};
      97                 :        7985 :     auto* original_backend{backend_coins_view};
      98                 :             : 
      99         [ +  + ]:        7985 :     if (is_db) coins_view_cache.SetBestBlock(uint256::ONE);
     100                 :        7985 :     COutPoint random_out_point;
     101                 :        7985 :     Coin random_coin;
     102         [ +  - ]:        7985 :     CMutableTransaction random_mutable_transaction;
     103   [ +  +  +  +  :     8522773 :     LIMITED_WHILE(good_data && fuzzed_data_provider.ConsumeBool(), 10'000)
                   +  + ]
     104                 :             :     {
     105         [ +  - ]:     4254029 :         CallOneOf(
     106                 :             :             fuzzed_data_provider,
     107                 :       88543 :             [&] {
     108         [ +  + ]:       88543 :                 if (random_coin.IsSpent()) {
     109                 :             :                     return;
     110                 :             :                 }
     111                 :       83206 :                 COutPoint outpoint{random_out_point};
     112                 :       83206 :                 Coin coin{random_coin};
     113         [ +  + ]:       83206 :                 if (fuzzed_data_provider.ConsumeBool()) {
     114                 :             :                     // We can only skip the check if no unspent coin exists for this outpoint.
     115   [ +  -  +  +  :      111695 :                     const bool possible_overwrite{coins_view_cache.PeekCoin(outpoint) || fuzzed_data_provider.ConsumeBool()};
                   +  + ]
     116         [ +  - ]:       63532 :                     coins_view_cache.AddCoin(outpoint, std::move(coin), possible_overwrite);
     117                 :             :                 } else {
     118         [ +  - ]:       19674 :                     coins_view_cache.EmplaceCoinInternalDANGER(std::move(outpoint), std::move(coin));
     119                 :             :                 }
     120                 :       83206 :             },
     121                 :     3390093 :             [&] {
     122                 :     3390093 :                 coins_view_cache.Flush(/*reallocate_cache=*/fuzzed_data_provider.ConsumeBool());
     123                 :     3390093 :             },
     124                 :       20011 :             [&] {
     125                 :       20011 :                 coins_view_cache.Sync();
     126                 :       20011 :             },
     127                 :       74101 :             [&] {
     128                 :       74101 :                 uint256 best_block{ConsumeUInt256(fuzzed_data_provider)};
     129                 :             :                 // `CCoinsViewDB::BatchWrite()` requires a non-null best block.
     130   [ +  +  +  + ]:      144539 :                 if (is_db && best_block.IsNull()) best_block = uint256::ONE;
     131                 :       74101 :                 coins_view_cache.SetBestBlock(best_block);
     132                 :       74101 :             },
     133                 :        1970 :             [&] {
     134                 :        1970 :                 (void)coins_view_cache.CreateResetGuard();
     135                 :             :                 // Reset() clears the best block, so reseed db-backed caches.
     136         [ +  + ]:        1970 :                 if (is_db) {
     137                 :         361 :                     const uint256 best_block{ConsumeUInt256(fuzzed_data_provider)};
     138         [ +  + ]:         722 :                     if (best_block.IsNull()) {
     139                 :          30 :                         good_data = false;
     140                 :          30 :                         return;
     141                 :             :                     }
     142                 :         331 :                     coins_view_cache.SetBestBlock(best_block);
     143                 :             :                 }
     144                 :             :             },
     145                 :      574570 :             [&] {
     146                 :      574570 :                 Coin move_to;
     147   [ +  +  +  - ]:      595752 :                 (void)coins_view_cache.SpendCoin(random_out_point, fuzzed_data_provider.ConsumeBool() ? &move_to : nullptr);
     148                 :      574570 :             },
     149                 :        6608 :             [&] {
     150                 :        6608 :                 coins_view_cache.Uncache(random_out_point);
     151                 :        6608 :             },
     152                 :       38137 :             [&] {
     153                 :       38137 :                 const bool use_original_backend{fuzzed_data_provider.ConsumeBool()};
     154   [ +  +  +  + ]:       38137 :                 if (use_original_backend && backend_coins_view != original_backend) {
     155                 :             :                     // FRESH flags valid against the empty backend may be invalid
     156                 :             :                     // against the original backend, so reset before restoring it.
     157                 :         132 :                     (void)coins_view_cache.CreateResetGuard();
     158                 :             :                     // Reset() clears the best block; db backends require a non-null hash.
     159         [ +  + ]:         132 :                     if (is_db) coins_view_cache.SetBestBlock(uint256::ONE);
     160                 :             :                 }
     161                 :       38137 :                 backend_coins_view = use_original_backend ? original_backend : &CoinsViewEmpty::Get();
     162                 :       38137 :                 coins_view_cache.SetBackend(*backend_coins_view);
     163                 :       38137 :             },
     164                 :        4898 :             [&] {
     165                 :        4898 :                 const std::optional<COutPoint> opt_out_point = ConsumeDeserializable<COutPoint>(fuzzed_data_provider);
     166         [ +  + ]:        4898 :                 if (!opt_out_point) {
     167                 :         109 :                     good_data = false;
     168                 :         109 :                     return;
     169                 :             :                 }
     170                 :        4789 :                 random_out_point = *opt_out_point;
     171                 :             :             },
     172                 :       24091 :             [&] {
     173                 :       24091 :                 const std::optional<Coin> opt_coin = ConsumeDeserializable<Coin>(fuzzed_data_provider);
     174         [ +  + ]:       24091 :                 if (!opt_coin) {
     175                 :         308 :                     good_data = false;
     176                 :         308 :                     return;
     177                 :             :                 }
     178                 :       23783 :                 random_coin = *opt_coin;
     179                 :       24091 :             },
     180                 :       13320 :             [&] {
     181                 :       13320 :                 const std::optional<CMutableTransaction> opt_mutable_transaction = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider, TX_WITH_WITNESS);
     182         [ +  + ]:       13320 :                 if (!opt_mutable_transaction) {
     183                 :         681 :                     good_data = false;
     184         [ -  + ]:         681 :                     return;
     185                 :             :                 }
     186         [ +  - ]:       12639 :                 random_mutable_transaction = *opt_mutable_transaction;
     187                 :       13320 :             },
     188                 :       17687 :             [&] {
     189                 :       17687 :                 CoinsCachePair sentinel{};
     190                 :       17687 :                 sentinel.second.SelfRef(sentinel);
     191                 :       17687 :                 size_t dirty_count{0};
     192         [ +  - ]:       17687 :                 CCoinsMapMemoryResource resource;
     193   [ +  -  +  - ]:       17687 :                 CCoinsMap coins_map{0, SaltedOutpointHasher{/*deterministic=*/true}, CCoinsMap::key_equal{}, &resource};
     194   [ +  -  +  +  :      958408 :                 LIMITED_WHILE(good_data && fuzzed_data_provider.ConsumeBool(), 10'000)
                   +  + ]
     195                 :             :                 {
     196                 :      940848 :                     CCoinsCacheEntry coins_cache_entry;
     197         [ +  + ]:      940848 :                     if (fuzzed_data_provider.ConsumeBool()) {
     198                 :      937338 :                         coins_cache_entry.coin = random_coin;
     199                 :             :                     } else {
     200                 :        3510 :                         const std::optional<Coin> opt_coin = ConsumeDeserializable<Coin>(fuzzed_data_provider);
     201         [ +  + ]:        3510 :                         if (!opt_coin) {
     202                 :         127 :                             good_data = false;
     203                 :         127 :                             return;
     204                 :             :                         }
     205                 :        3383 :                         coins_cache_entry.coin = *opt_coin;
     206                 :        3383 :                     }
     207                 :             :                     // Avoid setting FRESH for an outpoint that already exists unspent in the parent view.
     208   [ +  -  +  +  :      944937 :                     bool fresh{!coins_view_cache.PeekCoin(random_out_point) && fuzzed_data_provider.ConsumeBool()};
                   +  + ]
     209   [ +  +  +  + ]:      940721 :                     bool dirty{fresh || fuzzed_data_provider.ConsumeBool()};
     210         [ +  - ]:      940721 :                     auto it{coins_map.emplace(random_out_point, std::move(coins_cache_entry)).first};
     211         [ +  + ]:      940721 :                     if (dirty) CCoinsCacheEntry::SetDirty(*it, sentinel);
     212         [ +  + ]:      940721 :                     if (fresh) CCoinsCacheEntry::SetFresh(*it, sentinel);
     213                 :      940721 :                     dirty_count += dirty;
     214                 :      940848 :                 }
     215         [ +  - ]:       17560 :                 auto cursor{CoinsViewCacheCursor(dirty_count, sentinel, coins_map, /*will_erase=*/true)};
     216         [ +  - ]:       17560 :                 uint256 best_block{coins_view_cache.GetBestBlock()};
     217         [ +  + ]:       17560 :                 if (fuzzed_data_provider.ConsumeBool()) best_block = ConsumeUInt256(fuzzed_data_provider);
     218                 :             :                 // Set best block hash to non-null to satisfy the assertion in CCoinsViewDB::BatchWrite().
     219   [ +  +  +  + ]:       20349 :                 if (is_db && best_block.IsNull()) best_block = uint256::ONE;
     220         [ +  - ]:       17560 :                 coins_view_cache.BatchWrite(cursor, best_block);
     221                 :       17687 :             });
     222                 :             :     }
     223                 :             : 
     224                 :        7985 :     {
     225                 :        7985 :         bool expected_code_path = false;
     226                 :        7985 :         try {
     227         [ -  + ]:        7985 :             (void)coins_view_cache.Cursor();
     228         [ -  + ]:        7985 :         } catch (const std::logic_error&) {
     229                 :        7985 :             expected_code_path = true;
     230                 :        7985 :         }
     231                 :           0 :         assert(expected_code_path);
     232         [ +  - ]:        7985 :         (void)coins_view_cache.DynamicMemoryUsage();
     233         [ +  - ]:        7985 :         (void)coins_view_cache.EstimateSize();
     234         [ +  - ]:        7985 :         (void)coins_view_cache.GetBestBlock();
     235         [ +  - ]:        7985 :         (void)coins_view_cache.GetCacheSize();
     236         [ +  - ]:        7985 :         (void)coins_view_cache.GetHeadBlocks();
     237   [ +  -  +  - ]:        7985 :         (void)coins_view_cache.HaveInputs(CTransaction{random_mutable_transaction});
     238                 :             :     }
     239                 :             : 
     240                 :        7985 :     {
     241   [ +  +  +  + ]:        7985 :         if (is_db && backend_coins_view == original_backend) {
     242   [ +  -  -  + ]:        2657 :             assert(backend_coins_view->Cursor());
     243                 :             :         }
     244         [ +  - ]:        7985 :         (void)backend_coins_view->EstimateSize();
     245         [ +  - ]:        7985 :         (void)backend_coins_view->GetBestBlock();
     246         [ +  - ]:        7985 :         (void)backend_coins_view->GetHeadBlocks();
     247                 :             :     }
     248                 :             : 
     249         [ +  + ]:        7985 :     if (fuzzed_data_provider.ConsumeBool()) {
     250         [ +  - ]:        5900 :         CallOneOf(
     251                 :             :             fuzzed_data_provider,
     252                 :         454 :             [&] {
     253                 :         454 :                 const CTransaction transaction{random_mutable_transaction};
     254                 :         454 :                 bool is_spent = false;
     255         [ +  + ]:      503790 :                 for (const CTxOut& tx_out : transaction.vout) {
     256         [ +  + ]:      503336 :                     if (Coin{tx_out, 0, transaction.IsCoinBase()}.IsSpent()) {
     257                 :          40 :                         is_spent = true;
     258                 :             :                     }
     259                 :             :                 }
     260         [ +  + ]:         454 :                 if (is_spent) {
     261                 :             :                     // Avoid:
     262                 :             :                     // coins.cpp:69: void CCoinsViewCache::AddCoin(const COutPoint &, Coin &&, bool): Assertion `!coin.IsSpent()' failed.
     263                 :          20 :                     return;
     264                 :             :                 }
     265                 :         434 :                 const int height{int(fuzzed_data_provider.ConsumeIntegral<uint32_t>() >> 1)};
     266   [ +  +  +  + ]:         848 :                 const bool check_for_overwrite{transaction.IsCoinBase() || [&] {
     267   [ -  +  +  + ]:      372380 :                     for (uint32_t i{0}; i < transaction.vout.size(); ++i) {
     268         [ +  + ]:      371972 :                         if (coins_view_cache.PeekCoin(COutPoint{transaction.GetHash(), i})) return true;
     269                 :             :                     }
     270                 :         408 :                     return fuzzed_data_provider.ConsumeBool();
     271         [ +  - ]:         414 :                 }()}; // We can only skip the check if the current txid has no unspent outputs
     272         [ +  - ]:         434 :                 AddCoins(coins_view_cache, transaction, height, check_for_overwrite);
     273                 :         454 :             },
     274                 :        4003 :             [&] {
     275         [ +  - ]:        8006 :                 (void)ValidateInputsStandardness(CTransaction{random_mutable_transaction}, coins_view_cache);
     276                 :        4003 :             },
     277                 :         280 :             [&] {
     278         [ +  - ]:         280 :                 TxValidationState state;
     279                 :         280 :                 CAmount tx_fee_out;
     280         [ +  - ]:         280 :                 const CTransaction transaction{random_mutable_transaction};
     281         [ +  + ]:         280 :                 if (ContainsSpentInput(transaction, coins_view_cache)) {
     282                 :             :                     // Avoid:
     283                 :             :                     // consensus/tx_verify.cpp:171: bool Consensus::CheckTxInputs(const CTransaction &, TxValidationState &, const CCoinsViewCache &, int, CAmount &): Assertion `!coin.IsSpent()' failed.
     284                 :             :                     return;
     285                 :             :                 }
     286         [ +  - ]:         257 :                 TxValidationState dummy;
     287   [ +  -  +  + ]:         257 :                 if (!CheckTransaction(transaction, dummy)) {
     288                 :             :                     // It is not allowed to call CheckTxInputs if CheckTransaction failed
     289                 :         164 :                     return;
     290                 :             :                 }
     291   [ +  -  +  + ]:          93 :                 if (Consensus::CheckTxInputs(transaction, state, coins_view_cache, fuzzed_data_provider.ConsumeIntegralInRange<int>(0, std::numeric_limits<int>::max()), tx_fee_out)) {
     292         [ -  + ]:           9 :                     assert(MoneyRange(tx_fee_out));
     293                 :             :                 }
     294                 :         817 :             },
     295                 :         200 :             [&] {
     296                 :         200 :                 const CTransaction transaction{random_mutable_transaction};
     297         [ +  + ]:         200 :                 if (ContainsSpentInput(transaction, coins_view_cache)) {
     298                 :             :                     // Avoid:
     299                 :             :                     // consensus/tx_verify.cpp:130: unsigned int GetP2SHSigOpCount(const CTransaction &, const CCoinsViewCache &): Assertion `!coin.IsSpent()' failed.
     300                 :          84 :                     return;
     301                 :             :                 }
     302         [ +  - ]:         116 :                 (void)GetP2SHSigOpCount(transaction, coins_view_cache);
     303                 :         200 :             },
     304                 :         542 :             [&] {
     305                 :         542 :                 const CTransaction transaction{random_mutable_transaction};
     306         [ +  + ]:         542 :                 if (ContainsSpentInput(transaction, coins_view_cache)) {
     307                 :             :                     // Avoid:
     308                 :             :                     // consensus/tx_verify.cpp:130: unsigned int GetP2SHSigOpCount(const CTransaction &, const CCoinsViewCache &): Assertion `!coin.IsSpent()' failed.
     309                 :             :                     return;
     310                 :             :                 }
     311         [ +  + ]:         483 :                 const auto flags = script_verify_flags::from_int(fuzzed_data_provider.ConsumeIntegral<script_verify_flags::value_type>());
     312   [ +  +  +  +  :         483 :                 if (!transaction.vin.empty() && (flags & SCRIPT_VERIFY_WITNESS) != 0 && (flags & SCRIPT_VERIFY_P2SH) == 0) {
                   +  + ]
     313                 :             :                     // Avoid:
     314                 :             :                     // script/interpreter.cpp:1705: size_t CountWitnessSigOps(const CScript &, const CScript &, const CScriptWitness &, unsigned int): Assertion `(flags & SCRIPT_VERIFY_P2SH) != 0' failed.
     315                 :             :                     return;
     316                 :             :                 }
     317         [ +  - ]:         478 :                 (void)GetTransactionSigOpCost(transaction, coins_view_cache, flags);
     318                 :         542 :             },
     319                 :         421 :             [&] {
     320         [ +  - ]:         421 :                 (void)IsWitnessStandard(CTransaction{random_mutable_transaction}, coins_view_cache);
     321                 :         421 :             });
     322                 :             :     }
     323                 :             : 
     324                 :        7985 :     {
     325         [ +  - ]:        7985 :         const Coin& coin_using_access_coin = coins_view_cache.AccessCoin(random_out_point);
     326                 :        7985 :         const bool exists_using_access_coin = !(coin_using_access_coin == EMPTY_COIN);
     327         [ +  - ]:        7985 :         const bool exists_using_have_coin = coins_view_cache.HaveCoin(random_out_point);
     328         [ +  - ]:        7985 :         const bool exists_using_have_coin_in_cache = coins_view_cache.HaveCoinInCache(random_out_point);
     329   [ +  -  +  + ]:        7985 :         if (auto coin{coins_view_cache.GetCoin(random_out_point)}) {
     330         [ -  + ]:        5590 :             assert(*coin == coin_using_access_coin);
     331   [ +  -  -  + ]:        5590 :             assert(exists_using_access_coin && exists_using_have_coin_in_cache && exists_using_have_coin);
     332                 :             :         } else {
     333   [ +  -  -  + ]:        2395 :             assert(!exists_using_access_coin && !exists_using_have_coin_in_cache && !exists_using_have_coin);
     334                 :        7985 :         }
     335                 :             :         // If HaveCoin on the backend is true, it must also be on the cache if the coin wasn't spent.
     336         [ +  - ]:        7985 :         const bool exists_using_have_coin_in_backend = backend_coins_view->HaveCoin(random_out_point);
     337   [ +  +  +  + ]:        7985 :         if (!coin_using_access_coin.IsSpent() && exists_using_have_coin_in_backend) {
     338         [ -  + ]:         820 :             assert(exists_using_have_coin);
     339                 :             :         }
     340   [ +  -  +  + ]:        7985 :         if (auto coin{backend_coins_view->GetCoin(random_out_point)}) {
     341         [ -  + ]:         861 :             assert(exists_using_have_coin_in_backend);
     342                 :             :             // Note we can't assert that `coin_using_get_coin == *coin` because the coin in
     343                 :             :             // the cache may have been modified but not yet flushed.
     344                 :             :         } else {
     345         [ -  + ]:        7124 :             assert(!exists_using_have_coin_in_backend);
     346                 :        7985 :         }
     347                 :             :     }
     348                 :        7985 : }
     349                 :             : 
     350         [ +  - ]:        3224 : FUZZ_TARGET(coins_view, .init = initialize_coins_view)
     351                 :             : {
     352                 :        2766 :     FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
     353                 :        2766 :     CCoinsViewCache coins_view_cache{&CoinsViewEmpty::Get(), /*deterministic=*/true};
     354   [ +  -  +  - ]:        2766 :     TestCoinsView(fuzzed_data_provider, coins_view_cache, &CoinsViewEmpty::Get());
     355                 :        2766 : }
     356                 :             : 
     357         [ +  - ]:        4031 : FUZZ_TARGET(coins_view_db, .init = initialize_coins_view)
     358                 :             : {
     359                 :        3573 :     FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
     360                 :        3573 :     auto db_params = DBParams{
     361                 :             :         .path = "",
     362                 :             :         .cache_bytes = 1_MiB,
     363                 :             :         .memory_only = true,
     364                 :        3573 :     };
     365         [ +  - ]:        3573 :     CCoinsViewDB backend_coins_view{std::move(db_params), CoinsViewOptions{}};
     366         [ +  - ]:        3573 :     CCoinsViewCache coins_view_cache{&backend_coins_view, /*deterministic=*/true};
     367         [ +  - ]:        3573 :     TestCoinsView(fuzzed_data_provider, coins_view_cache, &backend_coins_view);
     368                 :        7146 : }
     369                 :             : 
     370                 :             : // Creates a CoinsViewOverlay and a MutationGuardCoinsViewCache as the base.
     371                 :             : // This allows us to exercise all methods on a CoinsViewOverlay, while also
     372                 :             : // ensuring that nothing can mutate the underlying cache until Flush or Sync is
     373                 :             : // called.
     374         [ +  - ]:        2104 : FUZZ_TARGET(coins_view_overlay, .init = initialize_coins_view)
     375                 :             : {
     376                 :        1646 :     FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
     377                 :        1646 :     MutationGuardCoinsViewCache backend_cache{&CoinsViewEmpty::Get(), /*deterministic=*/true};
     378         [ +  - ]:        1646 :     CoinsViewOverlay coins_view_cache{&backend_cache, /*deterministic=*/true};
     379         [ +  - ]:        1646 :     TestCoinsView(fuzzed_data_provider, coins_view_cache, &backend_cache);
     380                 :        1646 : }
        

Generated by: LCOV version 2.0-1