/root/bitcoin/src/coins.h
Line | Count | Source |
1 | | // Copyright (c) 2009-2010 Satoshi Nakamoto |
2 | | // Copyright (c) 2009-present The Bitcoin Core developers |
3 | | // Distributed under the MIT software license, see the accompanying |
4 | | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
5 | | |
6 | | #ifndef BITCOIN_COINS_H |
7 | | #define BITCOIN_COINS_H |
8 | | |
9 | | #include <attributes.h> |
10 | | #include <compressor.h> |
11 | | #include <core_memusage.h> |
12 | | #include <memusage.h> |
13 | | #include <primitives/transaction.h> |
14 | | #include <serialize.h> |
15 | | #include <support/allocators/pool.h> |
16 | | #include <uint256.h> |
17 | | #include <util/check.h> |
18 | | #include <util/overflow.h> |
19 | | #include <util/hasher.h> |
20 | | |
21 | | #include <cassert> |
22 | | #include <cstdint> |
23 | | |
24 | | #include <functional> |
25 | | #include <unordered_map> |
26 | | |
27 | | /** |
28 | | * A UTXO entry. |
29 | | * |
30 | | * Serialized format: |
31 | | * - VARINT((coinbase ? 1 : 0) | (height << 1)) |
32 | | * - the non-spent CTxOut (via TxOutCompression) |
33 | | */ |
34 | | class Coin |
35 | | { |
36 | | public: |
37 | | //! unspent transaction output |
38 | | CTxOut out; |
39 | | |
40 | | //! whether containing transaction was a coinbase |
41 | | unsigned int fCoinBase : 1; |
42 | | |
43 | | //! at which height this containing transaction was included in the active block chain |
44 | | uint32_t nHeight : 31; |
45 | | |
46 | | //! construct a Coin from a CTxOut and height/coinbase information. |
47 | 0 | Coin(CTxOut&& outIn, int nHeightIn, bool fCoinBaseIn) : out(std::move(outIn)), fCoinBase(fCoinBaseIn), nHeight(nHeightIn) {} |
48 | 0 | Coin(const CTxOut& outIn, int nHeightIn, bool fCoinBaseIn) : out(outIn), fCoinBase(fCoinBaseIn),nHeight(nHeightIn) {} |
49 | | |
50 | 0 | void Clear() { |
51 | 0 | out.SetNull(); |
52 | 0 | fCoinBase = false; |
53 | 0 | nHeight = 0; |
54 | 0 | } |
55 | | |
56 | | //! empty constructor |
57 | 0 | Coin() : fCoinBase(false), nHeight(0) { } |
58 | | |
59 | 0 | bool IsCoinBase() const { |
60 | 0 | return fCoinBase; |
61 | 0 | } |
62 | | |
63 | | template<typename Stream> |
64 | 0 | void Serialize(Stream &s) const { |
65 | 0 | assert(!IsSpent()); |
66 | 0 | uint32_t code = nHeight * uint32_t{2} + fCoinBase; |
67 | 0 | ::Serialize(s, VARINT(code)); Line | Count | Source | 492 | 0 | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
| ::Serialize(s, VARINT(code)); Line | Count | Source | 492 | 0 | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
|
68 | 0 | ::Serialize(s, Using<TxOutCompression>(out)); |
69 | 0 | } Unexecuted instantiation: void Coin::Serialize<DataStream>(DataStream&) const Unexecuted instantiation: void Coin::Serialize<AutoFile>(AutoFile&) const |
70 | | |
71 | | template<typename Stream> |
72 | 0 | void Unserialize(Stream &s) { |
73 | 0 | uint32_t code = 0; |
74 | 0 | ::Unserialize(s, VARINT(code)); Line | Count | Source | 492 | 0 | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
| ::Unserialize(s, VARINT(code)); Line | Count | Source | 492 | 0 | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
| ::Unserialize(s, VARINT(code)); Line | Count | Source | 492 | 0 | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
|
75 | 0 | nHeight = code >> 1; |
76 | 0 | fCoinBase = code & 1; |
77 | 0 | ::Unserialize(s, Using<TxOutCompression>(out)); |
78 | 0 | } Unexecuted instantiation: void Coin::Unserialize<SpanReader>(SpanReader&) Unexecuted instantiation: void Coin::Unserialize<DataStream>(DataStream&) Unexecuted instantiation: void Coin::Unserialize<AutoFile>(AutoFile&) |
79 | | |
80 | | /** Either this coin never existed (see e.g. coinEmpty in coins.cpp), or it |
81 | | * did exist and has been spent. |
82 | | */ |
83 | 0 | bool IsSpent() const { |
84 | 0 | return out.IsNull(); |
85 | 0 | } |
86 | | |
87 | 0 | size_t DynamicMemoryUsage() const { |
88 | 0 | return memusage::DynamicUsage(out.scriptPubKey); |
89 | 0 | } |
90 | | }; |
91 | | |
92 | | struct CCoinsCacheEntry; |
93 | | using CoinsCachePair = std::pair<const COutPoint, CCoinsCacheEntry>; |
94 | | |
95 | | /** |
96 | | * A Coin in one level of the coins database caching hierarchy. |
97 | | * |
98 | | * A coin can either be: |
99 | | * - unspent or spent (in which case the Coin object will be nulled out - see Coin.Clear()) |
100 | | * - DIRTY or not DIRTY |
101 | | * - FRESH or not FRESH |
102 | | * |
103 | | * Out of these 2^3 = 8 states, only some combinations are valid: |
104 | | * - unspent, FRESH, DIRTY (e.g. a new coin created in the cache) |
105 | | * - unspent, not FRESH, DIRTY (e.g. a coin changed in the cache during a reorg) |
106 | | * - unspent, not FRESH, not DIRTY (e.g. an unspent coin fetched from the parent cache) |
107 | | * - spent, not FRESH, DIRTY (e.g. a coin is spent and spentness needs to be flushed to the parent) |
108 | | */ |
109 | | struct CCoinsCacheEntry |
110 | | { |
111 | | private: |
112 | | /** |
113 | | * These are used to create a doubly linked list of flagged entries. |
114 | | * They are set in SetDirty, SetFresh, and unset in SetClean. |
115 | | * A flagged entry is any entry that is either DIRTY, FRESH, or both. |
116 | | * |
117 | | * DIRTY entries are tracked so that only modified entries can be passed to |
118 | | * the parent cache for batch writing. This is a performance optimization |
119 | | * compared to giving all entries in the cache to the parent and having the |
120 | | * parent scan for only modified entries. |
121 | | */ |
122 | | CoinsCachePair* m_prev{nullptr}; |
123 | | CoinsCachePair* m_next{nullptr}; |
124 | | uint8_t m_flags{0}; |
125 | | |
126 | | //! Adding a flag requires a reference to the sentinel of the flagged pair linked list. |
127 | | static void AddFlags(uint8_t flags, CoinsCachePair& pair, CoinsCachePair& sentinel) noexcept |
128 | 0 | { |
129 | 0 | Assume(flags & (DIRTY | FRESH)); Line | Count | Source | 125 | 0 | #define Assume(val) inline_assertion_check<false>(val, std::source_location::current(), #val) |
|
130 | 0 | if (!pair.second.m_flags) { |
131 | 0 | Assume(!pair.second.m_prev && !pair.second.m_next); Line | Count | Source | 125 | 0 | #define Assume(val) inline_assertion_check<false>(val, std::source_location::current(), #val) |
|
132 | 0 | pair.second.m_prev = sentinel.second.m_prev; |
133 | 0 | pair.second.m_next = &sentinel; |
134 | 0 | sentinel.second.m_prev = &pair; |
135 | 0 | pair.second.m_prev->second.m_next = &pair; |
136 | 0 | } |
137 | 0 | Assume(pair.second.m_prev && pair.second.m_next); Line | Count | Source | 125 | 0 | #define Assume(val) inline_assertion_check<false>(val, std::source_location::current(), #val) |
|
138 | 0 | pair.second.m_flags |= flags; |
139 | 0 | } |
140 | | |
141 | | public: |
142 | | Coin coin; // The actual cached data. |
143 | | |
144 | | enum Flags { |
145 | | /** |
146 | | * DIRTY means the CCoinsCacheEntry is potentially different from the |
147 | | * version in the parent cache. Failure to mark a coin as DIRTY when |
148 | | * it is potentially different from the parent cache will cause a |
149 | | * consensus failure, since the coin's state won't get written to the |
150 | | * parent when the cache is flushed. |
151 | | */ |
152 | | DIRTY = (1 << 0), |
153 | | /** |
154 | | * FRESH means the parent cache does not have this coin or that it is a |
155 | | * spent coin in the parent cache. If a FRESH coin in the cache is |
156 | | * later spent, it can be deleted entirely and doesn't ever need to be |
157 | | * flushed to the parent. This is a performance optimization. Marking a |
158 | | * coin as FRESH when it exists unspent in the parent cache will cause a |
159 | | * consensus failure, since it might not be deleted from the parent |
160 | | * when this cache is flushed. |
161 | | */ |
162 | | FRESH = (1 << 1), |
163 | | }; |
164 | | |
165 | 0 | CCoinsCacheEntry() noexcept = default; |
166 | 0 | explicit CCoinsCacheEntry(Coin&& coin_) noexcept : coin(std::move(coin_)) {} |
167 | | ~CCoinsCacheEntry() |
168 | 0 | { |
169 | 0 | SetClean(); |
170 | 0 | } |
171 | | |
172 | 0 | static void SetDirty(CoinsCachePair& pair, CoinsCachePair& sentinel) noexcept { AddFlags(DIRTY, pair, sentinel); } |
173 | 0 | static void SetFresh(CoinsCachePair& pair, CoinsCachePair& sentinel) noexcept { AddFlags(FRESH, pair, sentinel); } |
174 | | |
175 | | void SetClean() noexcept |
176 | 0 | { |
177 | 0 | if (!m_flags) return; |
178 | 0 | m_next->second.m_prev = m_prev; |
179 | 0 | m_prev->second.m_next = m_next; |
180 | 0 | m_flags = 0; |
181 | 0 | m_prev = m_next = nullptr; |
182 | 0 | } |
183 | 0 | bool IsDirty() const noexcept { return m_flags & DIRTY; } |
184 | 0 | bool IsFresh() const noexcept { return m_flags & FRESH; } |
185 | | |
186 | | //! Only call Next when this entry is DIRTY, FRESH, or both |
187 | | CoinsCachePair* Next() const noexcept |
188 | 0 | { |
189 | 0 | Assume(m_flags); Line | Count | Source | 125 | 0 | #define Assume(val) inline_assertion_check<false>(val, std::source_location::current(), #val) |
|
190 | 0 | return m_next; |
191 | 0 | } |
192 | | |
193 | | //! Only call Prev when this entry is DIRTY, FRESH, or both |
194 | | CoinsCachePair* Prev() const noexcept |
195 | 0 | { |
196 | 0 | Assume(m_flags); Line | Count | Source | 125 | 0 | #define Assume(val) inline_assertion_check<false>(val, std::source_location::current(), #val) |
|
197 | 0 | return m_prev; |
198 | 0 | } |
199 | | |
200 | | //! Only use this for initializing the linked list sentinel |
201 | | void SelfRef(CoinsCachePair& pair) noexcept |
202 | 0 | { |
203 | 0 | Assume(&pair.second == this); Line | Count | Source | 125 | 0 | #define Assume(val) inline_assertion_check<false>(val, std::source_location::current(), #val) |
|
204 | 0 | m_prev = &pair; |
205 | 0 | m_next = &pair; |
206 | | // Set sentinel to DIRTY so we can call Next on it |
207 | 0 | m_flags = DIRTY; |
208 | 0 | } |
209 | | }; |
210 | | |
211 | | /** |
212 | | * PoolAllocator's MAX_BLOCK_SIZE_BYTES parameter here uses sizeof the data, and adds the size |
213 | | * of 4 pointers. We do not know the exact node size used in the std::unordered_node implementation |
214 | | * because it is implementation defined. Most implementations have an overhead of 1 or 2 pointers, |
215 | | * so nodes can be connected in a linked list, and in some cases the hash value is stored as well. |
216 | | * Using an additional sizeof(void*)*4 for MAX_BLOCK_SIZE_BYTES should thus be sufficient so that |
217 | | * all implementations can allocate the nodes from the PoolAllocator. |
218 | | */ |
219 | | using CCoinsMap = std::unordered_map<COutPoint, |
220 | | CCoinsCacheEntry, |
221 | | SaltedOutpointHasher, |
222 | | std::equal_to<COutPoint>, |
223 | | PoolAllocator<CoinsCachePair, |
224 | | sizeof(CoinsCachePair) + sizeof(void*) * 4>>; |
225 | | |
226 | | using CCoinsMapMemoryResource = CCoinsMap::allocator_type::ResourceType; |
227 | | |
228 | | /** Cursor for iterating over CoinsView state */ |
229 | | class CCoinsViewCursor |
230 | | { |
231 | | public: |
232 | 0 | CCoinsViewCursor(const uint256 &hashBlockIn): hashBlock(hashBlockIn) {} |
233 | 0 | virtual ~CCoinsViewCursor() = default; |
234 | | |
235 | | virtual bool GetKey(COutPoint &key) const = 0; |
236 | | virtual bool GetValue(Coin &coin) const = 0; |
237 | | |
238 | | virtual bool Valid() const = 0; |
239 | | virtual void Next() = 0; |
240 | | |
241 | | //! Get best block at the time this cursor was created |
242 | 0 | const uint256 &GetBestBlock() const { return hashBlock; } |
243 | | private: |
244 | | uint256 hashBlock; |
245 | | }; |
246 | | |
247 | | /** |
248 | | * Cursor for iterating over the linked list of flagged entries in CCoinsViewCache. |
249 | | * |
250 | | * This is a helper struct to encapsulate the diverging logic between a non-erasing |
251 | | * CCoinsViewCache::Sync and an erasing CCoinsViewCache::Flush. This allows the receiver |
252 | | * of CCoinsView::BatchWrite to iterate through the flagged entries without knowing |
253 | | * the caller's intent. |
254 | | * |
255 | | * However, the receiver can still call CoinsViewCacheCursor::WillErase to see if the |
256 | | * caller will erase the entry after BatchWrite returns. If so, the receiver can |
257 | | * perform optimizations such as moving the coin out of the CCoinsCachEntry instead |
258 | | * of copying it. |
259 | | */ |
260 | | struct CoinsViewCacheCursor |
261 | | { |
262 | | //! If will_erase is not set, iterating through the cursor will erase spent coins from the map, |
263 | | //! and other coins will be unflagged (removing them from the linked list). |
264 | | //! If will_erase is set, the underlying map and linked list will not be modified, |
265 | | //! as the caller is expected to wipe the entire map anyway. |
266 | | //! This is an optimization compared to erasing all entries as the cursor iterates them when will_erase is set. |
267 | | //! Calling CCoinsMap::clear() afterwards is faster because a CoinsCachePair cannot be coerced back into a |
268 | | //! CCoinsMap::iterator to be erased, and must therefore be looked up again by key in the CCoinsMap before being erased. |
269 | | CoinsViewCacheCursor(size_t& dirty_count LIFETIMEBOUND, |
270 | | CoinsCachePair& sentinel LIFETIMEBOUND, |
271 | | CCoinsMap& map LIFETIMEBOUND, |
272 | | bool will_erase) noexcept |
273 | 0 | : m_dirty_count(dirty_count), m_sentinel(sentinel), m_map(map), m_will_erase(will_erase) {} |
274 | | |
275 | 0 | inline CoinsCachePair* Begin() const noexcept { return m_sentinel.second.Next(); } |
276 | 0 | inline CoinsCachePair* End() const noexcept { return &m_sentinel; } |
277 | | |
278 | | //! Return the next entry after current, possibly erasing current |
279 | | inline CoinsCachePair* NextAndMaybeErase(CoinsCachePair& current) noexcept |
280 | 0 | { |
281 | 0 | const auto next_entry{current.second.Next()}; |
282 | 0 | Assume(TrySub(m_dirty_count, current.second.IsDirty())); Line | Count | Source | 125 | 0 | #define Assume(val) inline_assertion_check<false>(val, std::source_location::current(), #val) |
|
283 | | // If we are not going to erase the cache, we must still erase spent entries. |
284 | | // Otherwise, clear the state of the entry. |
285 | 0 | if (!m_will_erase) { |
286 | 0 | if (current.second.coin.IsSpent()) { |
287 | 0 | assert(current.second.coin.DynamicMemoryUsage() == 0); // scriptPubKey was already cleared in SpendCoin |
288 | 0 | m_map.erase(current.first); |
289 | 0 | } else { |
290 | 0 | current.second.SetClean(); |
291 | 0 | } |
292 | 0 | } |
293 | 0 | return next_entry; |
294 | 0 | } |
295 | | |
296 | 0 | inline bool WillErase(CoinsCachePair& current) const noexcept { return m_will_erase || current.second.coin.IsSpent(); } |
297 | 0 | size_t GetDirtyCount() const noexcept { return m_dirty_count; } |
298 | 0 | size_t GetTotalCount() const noexcept { return m_map.size(); } |
299 | | private: |
300 | | size_t& m_dirty_count; |
301 | | CoinsCachePair& m_sentinel; |
302 | | CCoinsMap& m_map; |
303 | | bool m_will_erase; |
304 | | }; |
305 | | |
306 | | /** Abstract view on the open txout dataset. */ |
307 | | class CCoinsView |
308 | | { |
309 | | public: |
310 | | //! Retrieve the Coin (unspent transaction output) for a given outpoint. |
311 | | //! May populate the cache. Use PeekCoin() to perform a non-caching lookup. |
312 | | virtual std::optional<Coin> GetCoin(const COutPoint& outpoint) const; |
313 | | |
314 | | //! Retrieve the Coin (unspent transaction output) for a given outpoint, without caching results. |
315 | | //! Does not populate the cache. Use GetCoin() to cache the result. |
316 | | virtual std::optional<Coin> PeekCoin(const COutPoint& outpoint) const; |
317 | | |
318 | | //! Just check whether a given outpoint is unspent. |
319 | | //! May populate the cache. Use PeekCoin() to perform a non-caching lookup. |
320 | | virtual bool HaveCoin(const COutPoint &outpoint) const; |
321 | | |
322 | | //! Retrieve the block hash whose state this CCoinsView currently represents |
323 | | virtual uint256 GetBestBlock() const; |
324 | | |
325 | | //! Retrieve the range of blocks that may have been only partially written. |
326 | | //! If the database is in a consistent state, the result is the empty vector. |
327 | | //! Otherwise, a two-element vector is returned consisting of the new and |
328 | | //! the old block hash, in that order. |
329 | | virtual std::vector<uint256> GetHeadBlocks() const; |
330 | | |
331 | | //! Do a bulk modification (multiple Coin changes + BestBlock change). |
332 | | //! The passed cursor is used to iterate through the coins. |
333 | | virtual void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlock); |
334 | | |
335 | | //! Get a cursor to iterate over the whole state |
336 | | virtual std::unique_ptr<CCoinsViewCursor> Cursor() const; |
337 | | |
338 | | //! As we use CCoinsViews polymorphically, have a virtual destructor |
339 | 0 | virtual ~CCoinsView() = default; |
340 | | |
341 | | //! Estimate database size (0 if not implemented) |
342 | 0 | virtual size_t EstimateSize() const { return 0; } |
343 | | }; |
344 | | |
345 | | |
346 | | /** CCoinsView backed by another CCoinsView */ |
347 | | class CCoinsViewBacked : public CCoinsView |
348 | | { |
349 | | protected: |
350 | | CCoinsView *base; |
351 | | |
352 | | public: |
353 | | CCoinsViewBacked(CCoinsView *viewIn); |
354 | | std::optional<Coin> GetCoin(const COutPoint& outpoint) const override; |
355 | | std::optional<Coin> PeekCoin(const COutPoint& outpoint) const override; |
356 | | bool HaveCoin(const COutPoint &outpoint) const override; |
357 | | uint256 GetBestBlock() const override; |
358 | | std::vector<uint256> GetHeadBlocks() const override; |
359 | | void SetBackend(CCoinsView &viewIn); |
360 | | void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlock) override; |
361 | | std::unique_ptr<CCoinsViewCursor> Cursor() const override; |
362 | | size_t EstimateSize() const override; |
363 | | }; |
364 | | |
365 | | |
366 | | /** CCoinsView that adds a memory cache for transactions to another CCoinsView */ |
367 | | class CCoinsViewCache : public CCoinsViewBacked |
368 | | { |
369 | | private: |
370 | | const bool m_deterministic; |
371 | | |
372 | | protected: |
373 | | /** |
374 | | * Make mutable so that we can "fill the cache" even from Get-methods |
375 | | * declared as "const". |
376 | | */ |
377 | | mutable uint256 hashBlock; |
378 | | mutable CCoinsMapMemoryResource m_cache_coins_memory_resource{}; |
379 | | /* The starting sentinel of the flagged entry circular doubly linked list. */ |
380 | | mutable CoinsCachePair m_sentinel; |
381 | | mutable CCoinsMap cacheCoins; |
382 | | |
383 | | /* Cached dynamic memory usage for the inner Coin objects. */ |
384 | | mutable size_t cachedCoinsUsage{0}; |
385 | | /* Running count of dirty Coin cache entries. */ |
386 | | mutable size_t m_dirty_count{0}; |
387 | | |
388 | | /** |
389 | | * Discard all modifications made to this cache without flushing to the base view. |
390 | | * This can be used to efficiently reuse a cache instance across multiple operations. |
391 | | */ |
392 | | void Reset() noexcept; |
393 | | |
394 | | /* Fetch the coin from base. Used for cache misses in FetchCoin. */ |
395 | | virtual std::optional<Coin> FetchCoinFromBase(const COutPoint& outpoint) const; |
396 | | |
397 | | public: |
398 | | CCoinsViewCache(CCoinsView *baseIn, bool deterministic = false); |
399 | | |
400 | | /** |
401 | | * By deleting the copy constructor, we prevent accidentally using it when one intends to create a cache on top of a base cache. |
402 | | */ |
403 | | CCoinsViewCache(const CCoinsViewCache &) = delete; |
404 | | |
405 | | // Standard CCoinsView methods |
406 | | std::optional<Coin> GetCoin(const COutPoint& outpoint) const override; |
407 | | std::optional<Coin> PeekCoin(const COutPoint& outpoint) const override; |
408 | | bool HaveCoin(const COutPoint &outpoint) const override; |
409 | | uint256 GetBestBlock() const override; |
410 | | void SetBestBlock(const uint256 &hashBlock); |
411 | | void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlock) override; |
412 | 0 | std::unique_ptr<CCoinsViewCursor> Cursor() const override { |
413 | 0 | throw std::logic_error("CCoinsViewCache cursor iteration not supported."); |
414 | 0 | } |
415 | | |
416 | | /** |
417 | | * Check if we have the given utxo already loaded in this cache. |
418 | | * The semantics are the same as HaveCoin(), but no calls to |
419 | | * the backing CCoinsView are made. |
420 | | */ |
421 | | bool HaveCoinInCache(const COutPoint &outpoint) const; |
422 | | |
423 | | /** |
424 | | * Return a reference to Coin in the cache, or coinEmpty if not found. This is |
425 | | * more efficient than GetCoin. |
426 | | * |
427 | | * Generally, do not hold the reference returned for more than a short scope. |
428 | | * While the current implementation allows for modifications to the contents |
429 | | * of the cache while holding the reference, this behavior should not be relied |
430 | | * on! To be safe, best to not hold the returned reference through any other |
431 | | * calls to this cache. |
432 | | */ |
433 | | const Coin& AccessCoin(const COutPoint &output) const; |
434 | | |
435 | | /** |
436 | | * Add a coin. Set possible_overwrite to true if an unspent version may |
437 | | * already exist in the cache. |
438 | | */ |
439 | | void AddCoin(const COutPoint& outpoint, Coin&& coin, bool possible_overwrite); |
440 | | |
441 | | /** |
442 | | * Emplace a coin into cacheCoins without performing any checks, marking |
443 | | * the emplaced coin as dirty. |
444 | | * |
445 | | * NOT FOR GENERAL USE. Used only when loading coins from a UTXO snapshot. |
446 | | * @sa ChainstateManager::PopulateAndValidateSnapshot() |
447 | | */ |
448 | | void EmplaceCoinInternalDANGER(COutPoint&& outpoint, Coin&& coin); |
449 | | |
450 | | /** |
451 | | * Spend a coin. Pass moveto in order to get the deleted data. |
452 | | * If no unspent output exists for the passed outpoint, this call |
453 | | * has no effect. |
454 | | */ |
455 | | bool SpendCoin(const COutPoint &outpoint, Coin* moveto = nullptr); |
456 | | |
457 | | /** |
458 | | * Push the modifications applied to this cache to its base and wipe local state. |
459 | | * Failure to call this method or Sync() before destruction will cause the changes |
460 | | * to be forgotten. |
461 | | * If reallocate_cache is false, the cache will retain the same memory footprint |
462 | | * after flushing and should be destroyed to deallocate. |
463 | | */ |
464 | | void Flush(bool reallocate_cache = true); |
465 | | |
466 | | /** |
467 | | * Push the modifications applied to this cache to its base while retaining |
468 | | * the contents of this cache (except for spent coins, which we erase). |
469 | | * Failure to call this method or Flush() before destruction will cause the changes |
470 | | * to be forgotten. |
471 | | */ |
472 | | void Sync(); |
473 | | |
474 | | /** |
475 | | * Removes the UTXO with the given outpoint from the cache, if it is |
476 | | * not modified. |
477 | | */ |
478 | | void Uncache(const COutPoint &outpoint); |
479 | | |
480 | | //! Size of the cache (in number of transaction outputs) |
481 | | unsigned int GetCacheSize() const; |
482 | | |
483 | | //! Number of dirty cache entries (transaction outputs) |
484 | 0 | size_t GetDirtyCount() const noexcept { return m_dirty_count; } |
485 | | |
486 | | //! Calculate the size of the cache (in bytes) |
487 | | size_t DynamicMemoryUsage() const; |
488 | | |
489 | | //! Check whether all prevouts of the transaction are present in the UTXO set represented by this view |
490 | | bool HaveInputs(const CTransaction& tx) const; |
491 | | |
492 | | //! Force a reallocation of the cache map. This is required when downsizing |
493 | | //! the cache because the map's allocator may be hanging onto a lot of |
494 | | //! memory despite having called .clear(). |
495 | | //! |
496 | | //! See: https://stackoverflow.com/questions/42114044/how-to-release-unordered-map-memory |
497 | | void ReallocateCache(); |
498 | | |
499 | | //! Run an internal sanity check on the cache data structure. */ |
500 | | void SanityCheck() const; |
501 | | |
502 | | class ResetGuard |
503 | | { |
504 | | private: |
505 | | friend CCoinsViewCache; |
506 | | CCoinsViewCache& m_cache; |
507 | 0 | explicit ResetGuard(CCoinsViewCache& cache LIFETIMEBOUND) noexcept : m_cache{cache} {} |
508 | | |
509 | | public: |
510 | | ResetGuard(const ResetGuard&) = delete; |
511 | | ResetGuard& operator=(const ResetGuard&) = delete; |
512 | | ResetGuard(ResetGuard&&) = delete; |
513 | | ResetGuard& operator=(ResetGuard&&) = delete; |
514 | | |
515 | 0 | ~ResetGuard() { m_cache.Reset(); } |
516 | | }; |
517 | | |
518 | | //! Create a scoped guard that will call `Reset()` on this cache when it goes out of scope. |
519 | 0 | [[nodiscard]] ResetGuard CreateResetGuard() noexcept { return ResetGuard{*this}; } |
520 | | |
521 | | private: |
522 | | /** |
523 | | * @note this is marked const, but may actually append to `cacheCoins`, increasing |
524 | | * memory usage. |
525 | | */ |
526 | | CCoinsMap::iterator FetchCoin(const COutPoint &outpoint) const; |
527 | | }; |
528 | | |
529 | | /** |
530 | | * CCoinsViewCache overlay that avoids populating/mutating parent cache layers on cache misses. |
531 | | * |
532 | | * This is achieved by fetching coins from the base view using PeekCoin() instead of GetCoin(), |
533 | | * so intermediate CCoinsViewCache layers are not filled. |
534 | | * |
535 | | * Used during ConnectBlock() as an ephemeral, resettable top-level view that is flushed only |
536 | | * on success, so invalid blocks don't pollute the underlying cache. |
537 | | */ |
538 | | class CoinsViewOverlay : public CCoinsViewCache |
539 | | { |
540 | | private: |
541 | | std::optional<Coin> FetchCoinFromBase(const COutPoint& outpoint) const override |
542 | 0 | { |
543 | 0 | return base->PeekCoin(outpoint); |
544 | 0 | } |
545 | | |
546 | | public: |
547 | | using CCoinsViewCache::CCoinsViewCache; |
548 | | }; |
549 | | |
550 | | //! Utility function to add all of a transaction's outputs to a cache. |
551 | | //! When check is false, this assumes that overwrites are only possible for coinbase transactions. |
552 | | //! When check is true, the underlying view may be queried to determine whether an addition is |
553 | | //! an overwrite. |
554 | | // TODO: pass in a boolean to limit these possible overwrites to known |
555 | | // (pre-BIP34) cases. |
556 | | void AddCoins(CCoinsViewCache& cache, const CTransaction& tx, int nHeight, bool check = false); |
557 | | |
558 | | //! Utility function to find any unspent output with a given txid. |
559 | | //! This function can be quite expensive because in the event of a transaction |
560 | | //! which is not found in the cache, it can cause up to MAX_OUTPUTS_PER_BLOCK |
561 | | //! lookups to database, so it should be used with care. |
562 | | const Coin& AccessByTxid(const CCoinsViewCache& cache, const Txid& txid); |
563 | | |
564 | | /** |
565 | | * This is a minimally invasive approach to shutdown on LevelDB read errors from the |
566 | | * chainstate, while keeping user interface out of the common library, which is shared |
567 | | * between bitcoind, and bitcoin-qt and non-server tools. |
568 | | * |
569 | | * Writes do not need similar protection, as failure to write is handled by the caller. |
570 | | */ |
571 | | class CCoinsViewErrorCatcher final : public CCoinsViewBacked |
572 | | { |
573 | | public: |
574 | 0 | explicit CCoinsViewErrorCatcher(CCoinsView* view) : CCoinsViewBacked(view) {} |
575 | | |
576 | 0 | void AddReadErrCallback(std::function<void()> f) { |
577 | 0 | m_err_callbacks.emplace_back(std::move(f)); |
578 | 0 | } |
579 | | |
580 | | std::optional<Coin> GetCoin(const COutPoint& outpoint) const override; |
581 | | bool HaveCoin(const COutPoint &outpoint) const override; |
582 | | std::optional<Coin> PeekCoin(const COutPoint& outpoint) const override; |
583 | | |
584 | | private: |
585 | | /** A list of callbacks to execute upon leveldb read error. */ |
586 | | std::vector<std::function<void()>> m_err_callbacks; |
587 | | |
588 | | }; |
589 | | |
590 | | #endif // BITCOIN_COINS_H |