20 return std::vector<BlockHash>();
64 CCoinsMap::key_equal{}, &m_cache_coins_memory_resource),
75 const auto [ret, inserted] =
cacheCoins.try_emplace(outpoint);
81 if (ret->second.coin.IsSpent()) {
92 CCoinsMap::const_iterator it =
FetchCoin(outpoint);
96 coin = it->second.coin;
101 bool possible_overwrite) {
106 CCoinsMap::iterator it;
108 std::tie(it, inserted) =
110 std::forward_as_tuple(outpoint), std::tuple<>());
115 if (!possible_overwrite) {
116 if (!it->second.coin.IsSpent()) {
117 throw std::logic_error(
"Attempted to overwrite an unspent coin "
118 "(when possible_overwrite is false)");
133 fresh = !it->second.IsDirty();
135 it->second.coin = std::move(coin);
141 TRACE5(utxocache, add, outpoint.GetTxId().data(), outpoint.GetN(),
149 auto [it, inserted] =
150 cacheCoins.try_emplace(std::move(outpoint), std::move(coin));
157 bool check_for_overwrite) {
158 bool fCoinbase = tx.IsCoinBase();
159 const TxId txid = tx.GetId();
160 for (
size_t i = 0; i < tx.vout.size(); ++i) {
161 const COutPoint outpoint(txid, i);
163 check_for_overwrite ? cache.
HaveCoin(outpoint) : fCoinbase;
173 CCoinsMap::iterator it =
FetchCoin(outpoint);
178 TRACE5(utxocache, spent, outpoint.GetTxId().data(), outpoint.GetN(),
179 it->second.coin.GetHeight(),
180 it->second.coin.GetTxOut().nValue.ToString().c_str(),
181 it->second.coin.IsCoinBase());
183 *moveout = std::move(it->second.coin);
185 if (it->second.IsFresh()) {
189 it->second.coin.Clear();
197 CCoinsMap::const_iterator it =
FetchCoin(outpoint);
201 return it->second.coin;
205 CCoinsMap::const_iterator it =
FetchCoin(outpoint);
206 return it !=
cacheCoins.end() && !it->second.coin.IsSpent();
210 CCoinsMap::const_iterator it =
cacheCoins.find(outpoint);
211 return (it !=
cacheCoins.end() && !it->second.coin.IsSpent());
227 for (
auto it{cursor.
Begin()}; it != cursor.
End();
230 if (!it->second.IsDirty()) {
233 CCoinsMap::iterator itUs =
cacheCoins.find(it->first);
237 if (!(it->second.IsFresh() && it->second.coin.IsSpent())) {
240 itUs =
cacheCoins.try_emplace(it->first).first;
246 entry.
coin = std::move(it->second.coin);
248 entry.coin = it->second.coin;
255 if (it->second.IsFresh()) {
261 if (it->second.IsFresh() && !itUs->second.coin.IsSpent()) {
266 throw std::logic_error(
"FRESH flag misapplied to coin that "
267 "exists in parent cache");
270 if (itUs->second.IsFresh() && it->second.coin.IsSpent()) {
281 itUs->second.coin = std::move(it->second.coin);
283 itUs->second.coin = it->second.coin;
317 throw std::logic_error(
318 "Not all unspent flagged entries were cleared");
325 CCoinsMap::iterator it =
cacheCoins.find(outpoint);
326 if (it !=
cacheCoins.end() && !it->second.IsDirty() &&
327 !it->second.IsFresh()) {
329 TRACE5(utxocache, uncache, outpoint.GetTxId().data(), outpoint.GetN(),
330 it->second.coin.GetHeight(),
331 it->second.coin.GetTxOut().nValue.ToString().c_str(),
332 it->second.coin.IsCoinBase());
342 if (tx.IsCoinBase()) {
346 for (
size_t i = 0; i < tx.vin.size(); i++) {
367 size_t recomputed_usage = 0;
368 size_t count_flagged = 0;
371 if (entry.IsDirty()) {
374 if (entry.IsFresh()) {
377 if (entry.coin.IsSpent()) {
381 assert(attr != 2 && attr != 4 && attr != 7);
384 recomputed_usage += entry.coin.DynamicMemoryUsage();
387 if (entry.IsDirty() || entry.IsFresh()) {
392 size_t count_linked = 0;
394 it = it->second.Next()) {
396 assert(it->second.Next()->second.Prev() == it);
397 assert(it->second.Prev()->second.Next() == it);
399 assert(it->second.IsDirty() || it->second.IsFresh());
403 assert(count_linked == count_flagged);
426 }
catch (
const std::runtime_error &e) {
430 LogPrintf(
"Error reading from database: %s\n", e.what());
CCoinsView backed by another CCoinsView.
bool HaveCoin(const COutPoint &outpoint) const override
Just check whether a given outpoint is unspent.
BlockHash GetBestBlock() const override
Retrieve the block hash whose state this CCoinsView currently represents.
CCoinsViewCursor * Cursor() const override
Get a cursor to iterate over the whole state.
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
size_t EstimateSize() const override
Estimate database size (0 if not implemented)
void SetBackend(CCoinsView &viewIn)
std::vector< BlockHash > GetHeadBlocks() const override
Retrieve the range of blocks that may have been only partially written.
bool BatchWrite(CoinsViewCacheCursor &cursor, const BlockHash &hashBlock) override
Do a bulk modification (multiple Coin changes + BestBlock change).
CCoinsViewBacked(CCoinsView *viewIn)
CCoinsView that adds a memory cache for transactions to another CCoinsView.
CCoinsViewCache(CCoinsView *baseIn, bool deterministic=false)
void AddCoin(const COutPoint &outpoint, Coin coin, bool possible_overwrite)
Add a coin.
const bool m_deterministic
BlockHash GetBestBlock() const override
Retrieve the block hash whose state this CCoinsView currently represents.
CCoinsMapMemoryResource m_cache_coins_memory_resource
bool SpendCoin(const COutPoint &outpoint, Coin *moveto=nullptr)
Spend a coin.
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.
bool BatchWrite(CoinsViewCacheCursor &cursor, const BlockHash &hashBlock) override
Do a bulk modification (multiple Coin changes + BestBlock change).
void SetBestBlock(const BlockHash &hashBlock)
BlockHash hashBlock
Make mutable so that we can "fill the cache" even from Get-methods declared as "const".
unsigned int GetCacheSize() const
Calculate the size of the cache (in number of transaction outputs)
CCoinsMap::iterator FetchCoin(const COutPoint &outpoint) const
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
bool HaveCoinInCache(const COutPoint &outpoint) const
Check if we have the given utxo already loaded in this cache.
bool Flush()
Push the modifications applied to this cache to its base and wipe local state.
CoinsCachePair m_sentinel
The starting sentinel of the flagged entry circular doubly linked list.
size_t DynamicMemoryUsage() const
Calculate the size of the cache (in bytes)
bool Sync()
Push the modifications applied to this cache to its base while retaining the contents of this cache (...
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
Just check whether a given outpoint is unspent.
void SanityCheck() const
Run an internal sanity check on the cache data structure.
const Coin & AccessCoin(const COutPoint &output) const
Return a reference to Coin in the cache, or coinEmpty if not found.
void ReallocateCache()
Force a reallocation of the cache map.
Cursor for iterating over CoinsView state.
std::vector< std::function< void()> > m_err_callbacks
A list of callbacks to execute upon leveldb read error.
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
Abstract view on the open txout dataset.
virtual bool GetCoin(const COutPoint &outpoint, Coin &coin) const
Retrieve the Coin (unspent transaction output) for a given outpoint.
virtual CCoinsViewCursor * Cursor() const
Get a cursor to iterate over the whole state.
virtual std::vector< BlockHash > GetHeadBlocks() const
Retrieve the range of blocks that may have been only partially written.
virtual BlockHash GetBestBlock() const
Retrieve the block hash whose state this CCoinsView currently represents.
virtual bool HaveCoin(const COutPoint &outpoint) const
Just check whether a given outpoint is unspent.
virtual size_t EstimateSize() const
Estimate database size (0 if not implemented)
virtual bool BatchWrite(CoinsViewCacheCursor &cursor, const BlockHash &hashBlock)
Do a bulk modification (multiple Coin changes + BestBlock change).
An output of a transaction.
uint32_t GetHeight() const
static const size_t MAX_OUTPUTS_PER_TX
const Coin & AccessByTxid(const CCoinsViewCache &view, const TxId &txid)
Utility function to find any unspent output with a given txid.
static const Coin coinEmpty
void AddCoins(CCoinsViewCache &cache, const CTransaction &tx, int nHeight, bool check_for_overwrite)
Utility function to add all of a transaction's outputs to a cache.
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...
CCoinsMap::allocator_type::ResourceType CCoinsMapMemoryResource
static const uint64_t MAX_TX_SIZE
The maximum allowed size for a transaction, in bytes.
static size_t DynamicUsage(const int8_t &v)
Dynamic memory usage for built-in types is zero.
size_t GetSerializeSize(const T &t, int nVersion=0)
std::string ToString() const
A BlockHash is a unqiue identifier for a block.
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
Cursor for iterating over the linked list of flagged entries in CCoinsViewCache.
CoinsCachePair * NextAndMaybeErase(CoinsCachePair ¤t) noexcept
Return the next entry after current, possibly erasing current.
bool WillErase(CoinsCachePair ¤t) const noexcept
CoinsCachePair * Begin() const noexcept
CoinsCachePair * End() const noexcept
A TxId is the identifier of a transaction.
#define TRACE5(context, event, a, b, c, d, e)
bilingual_str _(const char *psz)
Translation function.
static const int PROTOCOL_VERSION
network protocol versioning