Repository: bitcoin/bitcoin
File: src/test/fuzz/coins_view.cpp (C++)

Code before:
}
} // namespace

void initialize_coins_view()
{
    static const auto testing_setup = MakeNoLogFileContext<>();
}

void TestCoinsView(FuzzedDataProvider& fuzzed_data_provider, CCoinsView& backend_coins_view, bool is_db)
{
    bool good_data{true};

    CCoinsViewCache coins_view_cache{&backend_coins_view, /*deterministic=*/true};
    if (is_db) coins_view_cache.SetBestBlock(uint256::ONE);
    COutPoint random_out_point;
    Coin random_coin;
    CMutableTransaction random_mutable_transaction;
    LIMITED_WHILE(good_data && fuzzed_data_provider.ConsumeBool(), 10'000)
    {
        CallOneOf(
            fuzzed_data_provider,
            [&] {
                if (random_coin.IsSpent()) {
                    return;
                }
                Coin coin = random_coin;
                bool expected_code_path = false;
                const bool possible_overwrite = fuzzed_data_provider.ConsumeBool();
                try {
                    coins_view_cache.AddCoin(random_out_point, std::move(coin), possible_overwrite);
                    expected_code_path = true;
                } catch (const std::logic_error& e) {
                    if (e.what() == std::string{"Attempted to overwrite an unspent coin (when possible_overwrite is false)"}) {
                        assert(!possible_overwrite);
                        expected_code_path = true;
                        // AddCoin() decreases cachedCoinsUsage by the memory usage of the old coin at the beginning and
                        // increases it by the value of the new coin at the end. If it throws in the process, the value
                        // of cachedCoinsUsage would have been incorrectly decreased, leading to an underflow later on.
                        // To avoid this, use Flush() to reset the value of cachedCoinsUsage in sync with the cacheCoins
                        // mapping.
                        (void)coins_view_cache.Flush();
                    }
                }
                assert(expected_code_path);
            },
            [&] {
                (void)coins_view_cache.Flush();
            },
            [&] {
                (void)coins_view_cache.Sync();
            },

Review comment (performance):
nit: This declaration of `outpoint` is enough to be placed in the `else` branch

``` diff
diff --git a/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp
index 3928120a3f..055c3c4b31 100644
--- a/src/test/fuzz/coins_view.cpp
+++ b/src/test/fuzz/coins_view.cpp
@@ -59,13 +59,12 @@ void TestCoinsView(FuzzedDataProvider& fuzzed_data_provider, CCoinsView& backend
                 if (random_coin.IsSpent()) {
                     return;
                 }
-                COutPoint outpoint{random_out_point};
                 Coin coin{random_coin};
                 if (fuzzed_data_provider.ConsumeBool()) {
                     bool expected_code_path = false;
                     const bool possible_overwrite = fuzzed_data_provider.ConsumeBool();
                     try {
-                        coins_view_cache.AddCoin(outpoint, std::move(coin), possible_overwrite);
+                        coins_view_cache.AddCoin(random_out_point, std::move(coin), possible_overwrite);
                         expected_code_path = true;
                     } catch (const std::logic_error& e) {
                         if (e.what() == std::string{"Attempted to overwrite an unspent coin (when possible_overwrite is false)"}) {
@@ -81,6 +80,7 @@ void TestCoinsView(FuzzedDataProvider& fuzzed_data_provider, CCoinsView& backend
                     }
                     assert(expected_code_path);
                 } else {
+                    COutPoint outpoint{random_out_point};
                     coins_view_cache.EmplaceCoinInternalDANGER(std::move(outpoint), std::move(coin));
                 }
             },
```

Code after:
}
} // namespace

void initialize_coins_view()
{
    static const auto testing_setup = MakeNoLogFileContext<>();
}

void TestCoinsView(FuzzedDataProvider& fuzzed_data_provider, CCoinsView& backend_coins_view, bool is_db)
{
    bool good_data{true};

    CCoinsViewCache coins_view_cache{&backend_coins_view, /*deterministic=*/true};
    if (is_db) coins_view_cache.SetBestBlock(uint256::ONE);
    COutPoint random_out_point;
    Coin random_coin;
    CMutableTransaction random_mutable_transaction;
    LIMITED_WHILE(good_data && fuzzed_data_provider.ConsumeBool(), 10'000)
    {
        CallOneOf(
            fuzzed_data_provider,
            [&] {
                if (random_coin.IsSpent()) {
                    return;
                }
                COutPoint outpoint{random_out_point};
                Coin coin{random_coin};
                if (fuzzed_data_provider.ConsumeBool()) {
                    const bool possible_overwrite{fuzzed_data_provider.ConsumeBool()};
                    try {
                        coins_view_cache.AddCoin(outpoint, std::move(coin), possible_overwrite);
                    } catch (const std::logic_error& e) {
                        assert(e.what() == std::string{"Attempted to overwrite an unspent coin (when possible_overwrite is false)"});
                        assert(!possible_overwrite);
                    }
                } else {
                    coins_view_cache.EmplaceCoinInternalDANGER(std::move(outpoint), std::move(coin));
                }
            },
            [&] {
                (void)coins_view_cache.Flush();
            },
            [&] {
                (void)coins_view_cache.Sync();
            },
            [&] {
                uint256 best_block{ConsumeUInt256(fuzzed_data_provider)};
                // Set best block hash to non-null to satisfy the assertion in CCoinsViewDB::BatchWrite().
                if (is_db && best_block.IsNull()) best_block = uint256::ONE;
                coins_view_cache.SetBestBlock(best_block);
            },