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

Code before:
                BOOST_CHECK(ret == !entry.IsSpent());
            }

            if (m_rng.randrange(5) == 0 || coin.IsSpent()) {
                Coin newcoin;
                newcoin.out.nValue = RandMoney(m_rng);
                newcoin.nHeight = 1;

                // Infrequently test adding unspendable coins.
                if (m_rng.randrange(16) == 0 && coin.IsSpent()) {
                    newcoin.out.scriptPubKey.assign(1 + m_rng.randbits(6), OP_RETURN);
                    BOOST_CHECK(newcoin.out.scriptPubKey.IsUnspendable());
                    added_an_unspendable_entry = true;
                } else {
                    // Random sizes so we can test memory usage accounting
                    newcoin.out.scriptPubKey.assign(m_rng.randbits(6), 0);
                    (coin.IsSpent() ? added_an_entry : updated_an_entry) = true;
                    coin = newcoin;
                }
                bool is_overwrite = !coin.IsSpent() || m_rng.rand32() & 1;
                stack.back()->AddCoin(COutPoint(txid, 0), std::move(newcoin), is_overwrite);
            } else {
                // Spend the coin.
                removed_an_entry = true;
                coin.Clear();
                BOOST_CHECK(stack.back()->SpendCoin(COutPoint(txid, 0)));
            }
        }

        // Once every 10 iterations, remove a random entry from the cache
        if (m_rng.randrange(10) == 0) {
            COutPoint out(txids[m_rng.rand32() % txids.size()], 0);
            int cacheid = m_rng.rand32() % stack.size();
            stack[cacheid]->Uncache(out);
            uncached_an_entry |= !stack[cacheid]->HaveCoinInCache(out);
        }

        // Once every 1000 iterations and at the end, verify the full cache.
        if (m_rng.randrange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) {
            for (const auto& entry : result) {
                bool have = stack.back()->HaveCoin(entry.first);
                const Coin& coin = stack.back()->AccessCoin(entry.first);
                BOOST_CHECK(have == !coin.IsSpent());
                BOOST_CHECK(coin == entry.second);
                if (coin.IsSpent()) {
                    missed_an_entry = true;
                } else {
                    BOOST_CHECK(stack.back()->HaveCoinInCache(entry.first));
                    found_an_entry = true;
                }
            }

Review comment (suggestion):
```suggestion
                if (COutPoint op(txid, 0); !stack.back()->map().contains(op) && !newcoin.out.scriptPubKey.IsUnspendable() && m_rng.randbool()) {
```

Code after:
                bool ret = stack.back()->HaveCoin(COutPoint(txid, 0));
                BOOST_CHECK(ret == !entry.IsSpent());
            }

            if (m_rng.randrange(5) == 0 || coin.IsSpent()) {
                Coin newcoin;
                newcoin.out.nValue = RandMoney(m_rng);
                newcoin.nHeight = 1;

                // Infrequently test adding unspendable coins.
                if (m_rng.randrange(16) == 0 && coin.IsSpent()) {
                    newcoin.out.scriptPubKey.assign(1 + m_rng.randbits(6), OP_RETURN);
                    BOOST_CHECK(newcoin.out.scriptPubKey.IsUnspendable());
                    added_an_unspendable_entry = true;
                } else {
                    // Random sizes so we can test memory usage accounting
                    newcoin.out.scriptPubKey.assign(m_rng.randbits(6), 0);
                    (coin.IsSpent() ? added_an_entry : updated_an_entry) = true;
                    coin = newcoin;
                }
                if (COutPoint op(txid, 0); !stack.back()->map().contains(op) && !newcoin.out.scriptPubKey.IsUnspendable() && m_rng.randbool()) {
                    stack.back()->EmplaceCoinInternalDANGER(std::move(op), std::move(newcoin));
                } else {
                    stack.back()->AddCoin(op, std::move(newcoin), /*possible_overwrite=*/!coin.IsSpent() || m_rng.randbool());
                }
            } else {
                // Spend the coin.
                removed_an_entry = true;
                coin.Clear();
                BOOST_CHECK(stack.back()->SpendCoin(COutPoint(txid, 0)));
            }
        }

        // Once every 10 iterations, remove a random entry from the cache
        if (m_rng.randrange(10) == 0) {
            COutPoint out(txids[m_rng.rand32() % txids.size()], 0);
            int cacheid = m_rng.rand32() % stack.size();
            stack[cacheid]->Uncache(out);
            uncached_an_entry |= !stack[cacheid]->HaveCoinInCache(out);
        }

        // Once every 1000 iterations and at the end, verify the full cache.
        if (m_rng.randrange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) {
            for (const auto& entry : result) {
                bool have = stack.back()->HaveCoin(entry.first);
                const Coin& coin = stack.back()->AccessCoin(entry.first);
                BOOST_CHECK(have == !coin.IsSpent());
                BOOST_CHECK(coin == entry.second);
                if (coin.IsSpent()) {
                    missed_an_entry = true;
                } else {