20 return std::vector<BlockHash>();
24 for (
auto it{cursor.
Begin()}; it != cursor.
End();
32 return GetCoin(outpoint).has_value();
65 CCoinsMap::key_equal{}, &m_cache_coins_memory_resource),
76 const auto [ret, inserted] =
cacheCoins.try_emplace(outpoint);
79 ret->second.coin = std::move(*coin);
81 Assert(!ret->second.coin.IsSpent());
92 it !=
cacheCoins.end() && !it->second.coin.IsSpent()) {
93 return it->second.coin;
99 bool possible_overwrite) {
104 CCoinsMap::iterator it;
106 std::tie(it, inserted) =
108 std::forward_as_tuple(outpoint), std::tuple<>());
110 if (!possible_overwrite) {
111 if (!it->second.coin.IsSpent()) {
112 throw std::logic_error(
"Attempted to overwrite an unspent coin "
113 "(when possible_overwrite is false)");
128 fresh = !it->second.IsDirty();
134 it->second.coin = std::move(coin);
141 TRACE5(utxocache, add, outpoint.GetTxId().data(), outpoint.GetN(),
148 const auto mem_usage{coin.DynamicMemoryUsage()};
149 auto [it, inserted] =
150 cacheCoins.try_emplace(std::move(outpoint), std::move(coin));
159 bool check_for_overwrite) {
160 bool fCoinbase = tx.IsCoinBase();
161 const TxId txid = tx.GetId();
162 for (
size_t i = 0; i < tx.vout.size(); ++i) {
163 const COutPoint outpoint(txid, i);
165 check_for_overwrite ? cache.
HaveCoin(outpoint) : fCoinbase;
175 CCoinsMap::iterator it =
FetchCoin(outpoint);
181 TRACE5(utxocache, spent, outpoint.GetTxId().data(), outpoint.GetN(),
182 it->second.coin.GetHeight(),
183 it->second.coin.GetTxOut().nValue.ToString().c_str(),
184 it->second.coin.IsCoinBase());
186 *moveout = std::move(it->second.coin);
188 if (it->second.IsFresh()) {
193 it->second.coin.Clear();
201 CCoinsMap::const_iterator it =
FetchCoin(outpoint);
205 return it->second.coin;
209 CCoinsMap::const_iterator it =
FetchCoin(outpoint);
210 return it !=
cacheCoins.end() && !it->second.coin.IsSpent();
214 CCoinsMap::const_iterator it =
cacheCoins.find(outpoint);
215 return (it !=
cacheCoins.end() && !it->second.coin.IsSpent());
231 for (
auto it{cursor.
Begin()}; it != cursor.
End();
233 if (!it->second.IsDirty()) {
237 auto [itUs, inserted]{
cacheCoins.try_emplace(it->first)};
239 if (it->second.IsFresh() && it->second.coin.IsSpent()) {
246 assert(entry.coin.DynamicMemoryUsage() == 0);
250 entry.coin = std::move(it->second.coin);
252 entry.coin = it->second.coin;
260 if (it->second.IsFresh()) {
266 if (it->second.IsFresh() && !itUs->second.coin.IsSpent()) {
271 throw std::logic_error(
"FRESH flag misapplied to coin that "
272 "exists in parent cache");
275 if (itUs->second.IsFresh() && it->second.coin.IsSpent()) {
280 itUs->second.coin.DynamicMemoryUsage()));
285 itUs->second.coin.DynamicMemoryUsage()));
289 itUs->second.coin = std::move(it->second.coin);
291 itUs->second.coin = it->second.coin;
294 if (!itUs->second.IsDirty()) {
314 if (reallocate_cache) {
327 throw std::logic_error(
"Not all unspent flagged entries were cleared");
339 CCoinsMap::iterator it =
cacheCoins.find(outpoint);
340 if (it !=
cacheCoins.end() && !it->second.IsDirty()) {
342 TRACE5(utxocache, uncache, outpoint.GetTxId().data(), outpoint.GetN(),
343 it->second.coin.GetHeight(),
344 it->second.coin.GetTxOut().nValue.ToString().c_str(),
345 it->second.coin.IsCoinBase());
355 if (tx.IsCoinBase()) {
359 for (
size_t i = 0; i < tx.vin.size(); i++) {
380 size_t recomputed_usage = 0;
381 size_t count_dirty = 0;
383 if (entry.coin.IsSpent()) {
385 assert(entry.IsDirty() && !entry.IsFresh());
388 assert(entry.IsDirty() || !entry.IsFresh());
392 recomputed_usage += entry.coin.DynamicMemoryUsage();
395 if (entry.IsDirty()) {
400 size_t count_linked = 0;
402 it = it->second.Next()) {
404 assert(it->second.Next()->second.Prev() == it);
405 assert(it->second.Prev()->second.Next() == it);
407 assert(it->second.IsDirty());
430template <
typename ReturnType,
typename Func>
433 const std::vector<std::function<
void()>> &err_callbacks) {
436 }
catch (
const std::runtime_error &e) {
437 for (
const auto &f : err_callbacks) {
440 LogError(
"Error reading from database: %s\n", e.what());
452 return ExecuteBackedWrapper<std::optional<Coin>>(
457 return ExecuteBackedWrapper<bool>(
#define Assert(val)
Identity function.
#define Assume(val)
Assume is the identity function.
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.
size_t EstimateSize() const override
Estimate database size (0 if not implemented)
std::optional< Coin > GetCoin(const COutPoint &outpoint) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
void SetBackend(CCoinsView &viewIn)
std::vector< BlockHash > GetHeadBlocks() const override
Retrieve the range of blocks that may have been only partially written.
void 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.
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)
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.
void BatchWrite(CoinsViewCacheCursor &cursor, const BlockHash &hashBlock) override
Do a bulk modification (multiple Coin changes + BestBlock change).
bool HaveInputs(const CTransaction &tx) const
Check whether all prevouts of the transaction are present in the UTXO set represented by this view.
void SetBestBlock(const BlockHash &hashBlock)
BlockHash hashBlock
Make mutable so that we can "fill the cache" even from Get-methods declared as "const".
void Flush(bool reallocate_cache=true)
Push the modifications applied to this cache to its base and wipe local state.
void Reset() noexcept
Discard all modifications made to this cache without flushing to the base view.
unsigned int GetCacheSize() const
Size of the cache (in number of transaction outputs)
CCoinsMap::iterator FetchCoin(const COutPoint &outpoint) const
bool HaveCoinInCache(const COutPoint &outpoint) const
Check if we have the given utxo already loaded in this cache.
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)
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.
std::optional< Coin > GetCoin(const COutPoint &outpoint) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
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::optional< Coin > GetCoin(const COutPoint &outpoint) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
std::vector< std::function< void()> > m_err_callbacks
A list of callbacks to execute upon leveldb read error.
bool HaveCoin(const COutPoint &outpoint) const override
Just check whether a given outpoint is unspent.
Abstract view on the open txout dataset.
virtual void BatchWrite(CoinsViewCacheCursor &cursor, const BlockHash &hashBlock)
Do a bulk modification (multiple Coin changes + BestBlock change).
virtual std::optional< Coin > GetCoin(const COutPoint &outpoint) 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)
An output of a transaction.
uint32_t GetHeight() const
static const uint256 ZERO
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
static ReturnType ExecuteBackedWrapper(Func func, const std::vector< std::function< void()> > &err_callbacks)
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.
bool Func(const std::string &str, Span< const char > &sp)
Parse a function call.
constexpr bool TrySub(T &i, const U j) noexcept
size_t GetSerializeSize(const T &t)
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.