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) {
75 const auto [ret, inserted] =
cacheCoins.try_emplace(outpoint);
78 ret->second.coin = std::move(*coin);
80 Assert(!ret->second.coin.IsSpent());
91 it !=
cacheCoins.end() && !it->second.coin.IsSpent()) {
92 return it->second.coin;
98 bool possible_overwrite) {
103 CCoinsMap::iterator it;
105 std::tie(it, inserted) =
107 std::forward_as_tuple(outpoint), std::tuple<>());
109 if (!possible_overwrite) {
110 if (!it->second.coin.IsSpent()) {
111 throw std::logic_error(
"Attempted to overwrite an unspent coin "
112 "(when possible_overwrite is false)");
127 fresh = !it->second.IsDirty();
133 it->second.coin = std::move(coin);
140 TRACE5(utxocache, add, outpoint.GetTxId().data(), outpoint.GetN(),
147 const auto mem_usage{coin.DynamicMemoryUsage()};
148 auto [it, inserted] =
149 cacheCoins.try_emplace(std::move(outpoint), std::move(coin));
158 bool check_for_overwrite) {
159 bool fCoinbase = tx.IsCoinBase();
160 const TxId txid = tx.GetId();
161 for (
size_t i = 0; i < tx.vout.size(); ++i) {
162 const COutPoint outpoint(txid, i);
164 check_for_overwrite ? cache.
HaveCoin(outpoint) : fCoinbase;
174 CCoinsMap::iterator it =
FetchCoin(outpoint);
180 TRACE5(utxocache, spent, outpoint.GetTxId().data(), outpoint.GetN(),
181 it->second.coin.GetHeight(),
182 it->second.coin.GetTxOut().nValue.ToString().c_str(),
183 it->second.coin.IsCoinBase());
185 *moveout = std::move(it->second.coin);
187 if (it->second.IsFresh()) {
192 it->second.coin.Clear();
200 CCoinsMap::const_iterator it =
FetchCoin(outpoint);
204 return it->second.coin;
208 CCoinsMap::const_iterator it =
FetchCoin(outpoint);
209 return it !=
cacheCoins.end() && !it->second.coin.IsSpent();
213 CCoinsMap::const_iterator it =
cacheCoins.find(outpoint);
214 return (it !=
cacheCoins.end() && !it->second.coin.IsSpent());
230 for (
auto it{cursor.
Begin()}; it != cursor.
End();
232 if (!it->second.IsDirty()) {
236 auto [itUs, inserted]{
cacheCoins.try_emplace(it->first)};
238 if (it->second.IsFresh() && it->second.coin.IsSpent()) {
245 assert(entry.coin.DynamicMemoryUsage() == 0);
249 entry.coin = std::move(it->second.coin);
251 entry.coin = it->second.coin;
259 if (it->second.IsFresh()) {
265 if (it->second.IsFresh() && !itUs->second.coin.IsSpent()) {
270 throw std::logic_error(
"FRESH flag misapplied to coin that "
271 "exists in parent cache");
274 if (itUs->second.IsFresh() && it->second.coin.IsSpent()) {
279 itUs->second.coin.DynamicMemoryUsage()));
284 itUs->second.coin.DynamicMemoryUsage()));
288 itUs->second.coin = std::move(it->second.coin);
290 itUs->second.coin = it->second.coin;
293 if (!itUs->second.IsDirty()) {
313 if (reallocate_cache) {
326 throw std::logic_error(
"Not all unspent flagged entries were cleared");
338 CCoinsMap::iterator it =
cacheCoins.find(outpoint);
339 if (it !=
cacheCoins.end() && !it->second.IsDirty()) {
341 TRACE5(utxocache, uncache, outpoint.GetTxId().data(), outpoint.GetN(),
342 it->second.coin.GetHeight(),
343 it->second.coin.GetTxOut().nValue.ToString().c_str(),
344 it->second.coin.IsCoinBase());
354 if (tx.IsCoinBase()) {
358 for (
size_t i = 0; i < tx.vin.size(); i++) {
379 size_t recomputed_usage = 0;
380 size_t count_dirty = 0;
382 if (entry.coin.IsSpent()) {
384 assert(entry.IsDirty() && !entry.IsFresh());
387 assert(entry.IsDirty() || !entry.IsFresh());
391 recomputed_usage += entry.coin.DynamicMemoryUsage();
394 if (entry.IsDirty()) {
399 size_t count_linked = 0;
401 it = it->second.Next()) {
403 assert(it->second.Next()->second.Prev() == it);
404 assert(it->second.Prev()->second.Next() == it);
406 assert(it->second.IsDirty());
429template <
typename ReturnType,
typename Func>
432 const std::vector<std::function<
void()>> &err_callbacks) {
435 }
catch (
const std::runtime_error &e) {
436 for (
const auto &f : err_callbacks) {
439 LogError(
"Error reading from database: %s\n", e.what());
451 return ExecuteBackedWrapper<std::optional<Coin>>(
456 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
constexpr bool IsNull() 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.