34const Coin EMPTY_COIN{};
52 struct CacheCoinSnapshot {
57 bool operator==(
const CacheCoinSnapshot&)
const =
default;
60 std::vector<CacheCoinSnapshot> ComputeCacheCoinsSnapshot()
const
62 std::vector<CacheCoinSnapshot> snapshot;
63 snapshot.reserve(cacheCoins.size());
65 for (
const auto& [outpoint, entry] : cacheCoins) {
66 snapshot.emplace_back(outpoint, entry.IsDirty(), entry.IsFresh(), entry.coin);
69 std::ranges::sort(snapshot, std::less<>{}, &CacheCoinSnapshot::outpoint);
73 mutable std::vector<CacheCoinSnapshot> m_expected_snapshot{ComputeCacheCoinsSnapshot()};
76 void BatchWrite(CoinsViewCacheCursor& cursor,
const uint256& block_hash)
override
79 assert(ComputeCacheCoinsSnapshot() == m_expected_snapshot);
81 m_expected_snapshot = ComputeCacheCoinsSnapshot();
104 fuzzed_data_provider,
110 Coin coin{random_coin};
113 const bool possible_overwrite{coins_view_cache.
PeekCoin(outpoint) || fuzzed_data_provider.
ConsumeBool()};
114 coins_view_cache.
AddCoin(outpoint, std::move(coin), possible_overwrite);
123 coins_view_cache.
Sync();
138 if (best_block.
IsNull()) {
147 (void)coins_view_cache.
SpendCoin(random_out_point, fuzzed_data_provider.
ConsumeBool() ? &move_to :
nullptr);
150 coins_view_cache.
Uncache(random_out_point);
156 coins_view_cache.
SetBackend(backend_coins_view);
160 if (!opt_out_point) {
164 random_out_point = *opt_out_point;
172 random_coin = *opt_coin;
176 if (!opt_mutable_transaction) {
180 random_mutable_transaction = *opt_mutable_transaction;
184 sentinel.second.SelfRef(sentinel);
185 size_t dirty_count{0};
192 coins_cache_entry.
coin = random_coin;
199 coins_cache_entry.
coin = *opt_coin;
202 bool fresh{!coins_view_cache.
PeekCoin(random_out_point) && fuzzed_data_provider.
ConsumeBool()};
203 bool dirty{fresh || fuzzed_data_provider.
ConsumeBool()};
204 auto it{coins_map.emplace(random_out_point, std::move(coins_cache_entry)).first};
207 dirty_count += dirty;
214 coins_view_cache.
BatchWrite(cursor, best_block);
219 bool expected_code_path =
false;
221 (void)coins_view_cache.
Cursor();
222 }
catch (
const std::logic_error&) {
223 expected_code_path =
true;
225 assert(expected_code_path);
236 std::unique_ptr<CCoinsViewCursor> coins_view_cursor = backend_coins_view.
Cursor();
237 assert(!!coins_view_cursor);
246 fuzzed_data_provider,
248 const CTransaction transaction{random_mutable_transaction};
249 bool is_spent =
false;
250 for (
const CTxOut& tx_out : transaction.
vout) {
260 const int height{int(fuzzed_data_provider.
ConsumeIntegral<uint32_t>() >> 1)};
261 const bool check_for_overwrite{transaction.
IsCoinBase() || [&] {
262 for (uint32_t i{0}; i < transaction.
vout.size(); ++i) {
267 AddCoins(coins_view_cache, transaction, height, check_for_overwrite);
275 const CTransaction transaction{random_mutable_transaction};
291 const CTransaction transaction{random_mutable_transaction};
300 const CTransaction transaction{random_mutable_transaction};
320 const Coin& coin_using_access_coin = coins_view_cache.
AccessCoin(random_out_point);
321 const bool exists_using_access_coin = !(coin_using_access_coin == EMPTY_COIN);
322 const bool exists_using_have_coin = coins_view_cache.
HaveCoin(random_out_point);
323 const bool exists_using_have_coin_in_cache = coins_view_cache.
HaveCoinInCache(random_out_point);
324 if (
auto coin{coins_view_cache.
GetCoin(random_out_point)}) {
325 assert(*coin == coin_using_access_coin);
326 assert(exists_using_access_coin && exists_using_have_coin_in_cache && exists_using_have_coin);
328 assert(!exists_using_access_coin && !exists_using_have_coin_in_cache && !exists_using_have_coin);
331 const bool exists_using_have_coin_in_backend = backend_coins_view.
HaveCoin(random_out_point);
332 if (!coin_using_access_coin.
IsSpent() && exists_using_have_coin_in_backend) {
333 assert(exists_using_have_coin);
335 if (
auto coin{backend_coins_view.
GetCoin(random_out_point)}) {
336 assert(exists_using_have_coin_in_backend);
340 assert(!exists_using_have_coin_in_backend);
350 TestCoinsView(fuzzed_data_provider, coins_view_cache, backend_coins_view,
false);
358 .cache_bytes = 1_MiB,
363 TestCoinsView(fuzzed_data_provider, coins_view_cache, backend_coins_view,
true);
374 MutationGuardCoinsViewCache backend_cache{&backend_base_coins_view,
true};
376 TestCoinsView(fuzzed_data_provider, coins_view_cache, backend_cache,
false);
bool MoneyRange(const CAmount &nValue)
int64_t CAmount
Amount in satoshis (Can be negative).
size_t EstimateSize() const override
Estimate database size (0 if not implemented).
void SetBackend(CCoinsView &viewIn)
std::vector< uint256 > GetHeadBlocks() const override
CCoinsView that adds a memory cache for transactions to another CCoinsView.
void Sync()
Push the modifications applied to this cache to its base while retaining the contents of this cache (...
CCoinsViewCache(CCoinsView *baseIn, bool deterministic=false)
std::unique_ptr< CCoinsViewCursor > Cursor() const override
Get a cursor to iterate over the whole state.
bool SpendCoin(const COutPoint &outpoint, Coin *moveto=nullptr)
Spend a coin.
ResetGuard CreateResetGuard() noexcept
Create a scoped guard that will call Reset() on this cache when it goes out of scope.
void Uncache(const COutPoint &outpoint)
Removes the UTXO with the given outpoint from the cache, if it is not modified.
bool HaveInputs(const CTransaction &tx) const
Check whether all prevouts of the transaction are present in the UTXO set represented by this view.
void AddCoin(const COutPoint &outpoint, Coin &&coin, bool possible_overwrite)
Add a coin.
void Flush(bool reallocate_cache=true)
Push the modifications applied to this cache to its base and wipe local state.
unsigned int GetCacheSize() const
Size of the cache (in number of transaction outputs).
uint256 GetBestBlock() const override
Retrieve the block hash whose state this CCoinsView currently represents.
void SetBestBlock(const uint256 &hashBlock)
bool HaveCoinInCache(const COutPoint &outpoint) const
Check if we have the given utxo already loaded in this cache.
size_t DynamicMemoryUsage() const
Calculate the size of the cache (in bytes).
void BatchWrite(CoinsViewCacheCursor &cursor, const uint256 &hashBlock) override
std::optional< Coin > PeekCoin(const COutPoint &outpoint) const override
void EmplaceCoinInternalDANGER(COutPoint &&outpoint, Coin &&coin)
Emplace a coin into cacheCoins without performing any checks, marking the emplaced coin as dirty.
bool HaveCoin(const COutPoint &outpoint) const override
std::optional< Coin > GetCoin(const COutPoint &outpoint) const override
const Coin & AccessCoin(const COutPoint &output) const
Return a reference to Coin in the cache, or coinEmpty if not found.
CCoinsView backed by the coin database (chainstate/).
Abstract view on the open txout dataset.
virtual std::optional< Coin > GetCoin(const COutPoint &outpoint) const
virtual std::vector< uint256 > GetHeadBlocks() const
virtual bool HaveCoin(const COutPoint &outpoint) const
virtual size_t EstimateSize() const
Estimate database size (0 if not implemented).
virtual std::unique_ptr< CCoinsViewCursor > Cursor() const
Get a cursor to iterate over the whole state.
virtual uint256 GetBestBlock() const
Retrieve the block hash whose state this CCoinsView currently represents.
An outpoint - a combination of a transaction hash and an index n into its vout.
The basic transaction that is broadcasted on the network and contained in blocks.
const std::vector< CTxOut > vout
const std::vector< CTxIn > vin
An output of a transaction.
CTxOut out
unspent transaction output
bool IsSpent() const
Either this coin never existed (see e.g.
uint32_t nHeight
at which height this containing transaction was included in the active block chain
unsigned int fCoinBase
whether containing transaction was a coinbase
CCoinsViewCache overlay that avoids populating/mutating parent cache layers on cache misses.
T ConsumeIntegralInRange(T min, T max)
constexpr bool IsNull() const
static constexpr script_verify_flags from_int(value_type f)
void AddCoins(CCoinsViewCache &cache, const CTransaction &tx, int nHeight, bool check_for_overwrite)
std::unordered_map< COutPoint, CCoinsCacheEntry, SaltedOutpointHasher, std::equal_to< COutPoint >, PoolAllocator< CoinsCachePair, sizeof(CoinsCachePair)+sizeof(void *) *4 > > CCoinsMap
PoolAllocator's MAX_BLOCK_SIZE_BYTES parameter here uses sizeof the data, and adds the size of 4 poin...
std::pair< const COutPoint, CCoinsCacheEntry > CoinsCachePair
CCoinsMap::allocator_type::ResourceType CCoinsMapMemoryResource
void initialize_coins_view()
void TestCoinsView(FuzzedDataProvider &fuzzed_data_provider, CCoinsViewCache &coins_view_cache, CCoinsView &backend_coins_view, bool is_db)
#define LIMITED_WHILE(condition, limit)
Can be used to limit a theoretically unbounded loop.
bool CheckTxInputs(const CTransaction &tx, TxValidationState &state, const CCoinsViewCache &inputs, int nSpendHeight, CAmount &txfee)
Check whether all inputs of this transaction are valid (no double spends and amounts) This does not m...
bool operator==(const CNetAddr &a, const CNetAddr &b)
bool AreInputsStandard(const CTransaction &tx, const CCoinsViewCache &mapInputs)
Check transaction inputs.
bool IsWitnessStandard(const CTransaction &tx, const CCoinsViewCache &mapInputs)
Check if the transaction is over standard P2WSH resources limit: 3600bytes witnessScript size,...
static constexpr TransactionSerParams TX_WITH_WITNESS
std::unique_ptr< T > MakeNoLogFileContext(const ChainType chain_type=ChainType::REGTEST, TestOpts opts={})
Make a test setup that has disk access to the debug.log file disabled.
A Coin in one level of the coins database caching hierarchy.
static void SetFresh(CoinsCachePair &pair, CoinsCachePair &sentinel) noexcept
static void SetDirty(CoinsCachePair &pair, CoinsCachePair &sentinel) noexcept
A mutable version of CTransaction.
Cursor for iterating over the linked list of flagged entries in CCoinsViewCache.
User-controlled performance and debug options.
Application-specific storage settings.
bool ContainsSpentInput(const CTransaction &tx, const CCoinsViewCache &inputs) noexcept
uint256 ConsumeUInt256(FuzzedDataProvider &fuzzed_data_provider) noexcept
size_t CallOneOf(FuzzedDataProvider &fuzzed_data_provider, Callables... callables)
std::optional< T > ConsumeDeserializable(FuzzedDataProvider &fuzzed_data_provider, const P ¶ms, const std::optional< size_t > &max_length=std::nullopt) noexcept
bool CheckTransaction(const CTransaction &tx, TxValidationState &state)
int64_t GetTransactionSigOpCost(const CTransaction &tx, const CCoinsViewCache &inputs, script_verify_flags flags)
Compute total signature operation cost of a transaction.
unsigned int GetP2SHSigOpCount(const CTransaction &tx, const CCoinsViewCache &inputs)
Count ECDSA signature operations in pay-to-script-hash inputs.