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 <crypto/siphash.h> |
13 | | #include <memusage.h> |
14 | | #include <primitives/transaction.h> |
15 | | #include <primitives/transaction_identifier.h> |
16 | | #include <serialize.h> |
17 | | #include <support/allocators/pool.h> |
18 | | #include <uint256.h> |
19 | | #include <util/check.h> |
20 | | #include <util/log.h> |
21 | | #include <util/overflow.h> |
22 | | |
23 | | #include <cassert> |
24 | | #include <cstdint> |
25 | | |
26 | | #include <atomic> |
27 | | #include <functional> |
28 | | #include <future> |
29 | | #include <memory> |
30 | | #include <optional> |
31 | | #include <unordered_map> |
32 | | #include <utility> |
33 | | #include <vector> |
34 | | |
35 | | class CBlock; |
36 | | class ThreadPool; |
37 | | |
38 | | /** |
39 | | * A UTXO entry. |
40 | | * |
41 | | * Serialized format: |
42 | | * - VARINT((height << 1) | (coinbase ? 1 : 0)) |
43 | | * - the non-spent CTxOut (via TxOutCompression) |
44 | | */ |
45 | | class Coin |
46 | | { |
47 | | public: |
48 | | //! unspent transaction output |
49 | | CTxOut out; |
50 | | |
51 | | //! whether containing transaction was a coinbase |
52 | | bool fCoinBase : 1; |
53 | | |
54 | | //! at which height this containing transaction was included in the active block chain |
55 | | uint32_t nHeight : 31; |
56 | | |
57 | | //! construct a Coin from a CTxOut and height/coinbase information. |
58 | 66 | Coin(CTxOut&& outIn, int nHeightIn, bool fCoinBaseIn) : out(std::move(outIn)), fCoinBase(fCoinBaseIn), nHeight(nHeightIn) {} |
59 | 17.4M | Coin(const CTxOut& outIn, int nHeightIn, bool fCoinBaseIn) : out(outIn), fCoinBase(fCoinBaseIn),nHeight(nHeightIn) {} |
60 | | |
61 | 11.0M | void Clear() { |
62 | 11.0M | out.SetNull(); |
63 | 11.0M | fCoinBase = false; |
64 | 11.0M | nHeight = 0; |
65 | 11.0M | } |
66 | | |
67 | | //! empty constructor |
68 | 62.7M | Coin() : fCoinBase(false), nHeight(0) { } |
69 | | |
70 | 11.4M | bool IsCoinBase() const { |
71 | 11.4M | return fCoinBase; |
72 | 11.4M | } |
73 | | |
74 | | template<typename Stream> |
75 | 297k | void Serialize(Stream &s) const { |
76 | 297k | assert(!IsSpent()); |
77 | 297k | uint32_t code{(uint32_t{nHeight} << 1) | uint32_t{fCoinBase}}; |
78 | 297k | ::Serialize(s, VARINT(code)); |
79 | 297k | ::Serialize(s, Using<TxOutCompression>(out)); |
80 | 297k | } void Coin::Serialize<AutoFile>(AutoFile&) const Line | Count | Source | 75 | 6.58k | void Serialize(Stream &s) const { | 76 | 6.58k | assert(!IsSpent()); | 77 | 6.58k | uint32_t code{(uint32_t{nHeight} << 1) | uint32_t{fCoinBase}}; | 78 | 6.58k | ::Serialize(s, VARINT(code)); | 79 | 6.58k | ::Serialize(s, Using<TxOutCompression>(out)); | 80 | 6.58k | } |
void Coin::Serialize<DataStream>(DataStream&) const Line | Count | Source | 75 | 290k | void Serialize(Stream &s) const { | 76 | 290k | assert(!IsSpent()); | 77 | 290k | uint32_t code{(uint32_t{nHeight} << 1) | uint32_t{fCoinBase}}; | 78 | 290k | ::Serialize(s, VARINT(code)); | 79 | 290k | ::Serialize(s, Using<TxOutCompression>(out)); | 80 | 290k | } |
|
81 | | |
82 | | template<typename Stream> |
83 | 371k | void Unserialize(Stream &s) { |
84 | 371k | uint32_t code = 0; |
85 | 371k | ::Unserialize(s, VARINT(code)); |
86 | 371k | nHeight = code >> 1; |
87 | 371k | fCoinBase = code & 1; |
88 | 371k | ::Unserialize(s, Using<TxOutCompression>(out)); |
89 | 371k | } void Coin::Unserialize<SpanReader>(SpanReader&) Line | Count | Source | 83 | 96.2k | void Unserialize(Stream &s) { | 84 | 96.2k | uint32_t code = 0; | 85 | 96.2k | ::Unserialize(s, VARINT(code)); | 86 | 96.2k | nHeight = code >> 1; | 87 | 96.2k | fCoinBase = code & 1; | 88 | 96.2k | ::Unserialize(s, Using<TxOutCompression>(out)); | 89 | 96.2k | } |
void Coin::Unserialize<AutoFile>(AutoFile&) Line | Count | Source | 83 | 6.35k | void Unserialize(Stream &s) { | 84 | 6.35k | uint32_t code = 0; | 85 | 6.35k | ::Unserialize(s, VARINT(code)); | 86 | 6.35k | nHeight = code >> 1; | 87 | 6.35k | fCoinBase = code & 1; | 88 | 6.35k | ::Unserialize(s, Using<TxOutCompression>(out)); | 89 | 6.35k | } |
void Coin::Unserialize<DataStream>(DataStream&) Line | Count | Source | 83 | 268k | void Unserialize(Stream &s) { | 84 | 268k | uint32_t code = 0; | 85 | 268k | ::Unserialize(s, VARINT(code)); | 86 | 268k | nHeight = code >> 1; | 87 | 268k | fCoinBase = code & 1; | 88 | 268k | ::Unserialize(s, Using<TxOutCompression>(out)); | 89 | 268k | } |
|
90 | | |
91 | | /** Either this coin never existed (see e.g. coinEmpty in coins.cpp), or it |
92 | | * did exist and has been spent. |
93 | | */ |
94 | 107M | bool IsSpent() const { |
95 | 107M | return out.IsNull(); |
96 | 107M | } |
97 | | |
98 | 42.1M | size_t DynamicMemoryUsage() const { |
99 | 42.1M | return memusage::DynamicUsage(out.scriptPubKey); |
100 | 42.1M | } |
101 | | }; |
102 | | |
103 | | struct CCoinsCacheEntry; |
104 | | using CoinsCachePair = std::pair<const COutPoint, CCoinsCacheEntry>; |
105 | | |
106 | | /** |
107 | | * A Coin in one level of the coins database caching hierarchy. |
108 | | * |
109 | | * A coin can either be: |
110 | | * - unspent or spent (in which case the Coin object will be nulled out - see Coin.Clear()) |
111 | | * - DIRTY or not DIRTY |
112 | | * - FRESH or not FRESH |
113 | | * |
114 | | * Out of these 2^3 = 8 states, only some combinations are valid: |
115 | | * - unspent, FRESH, DIRTY (e.g. a new coin created in the cache) |
116 | | * - unspent, not FRESH, DIRTY (e.g. a coin changed in the cache during a reorg) |
117 | | * - unspent, not FRESH, not DIRTY (e.g. an unspent coin fetched from the parent cache) |
118 | | * - spent, not FRESH, DIRTY (e.g. a coin is spent and spentness needs to be flushed to the parent) |
119 | | */ |
120 | | struct CCoinsCacheEntry |
121 | | { |
122 | | private: |
123 | | /** |
124 | | * These are used to create a doubly linked list of flagged entries. |
125 | | * They are set in SetDirty, SetFresh, and unset in SetClean. |
126 | | * A flagged entry is any entry that is either DIRTY, FRESH, or both. |
127 | | * |
128 | | * DIRTY entries are tracked so that only modified entries can be passed to |
129 | | * the parent cache for batch writing. This is a performance optimization |
130 | | * compared to giving all entries in the cache to the parent and having the |
131 | | * parent scan for only modified entries. |
132 | | */ |
133 | | CoinsCachePair* m_prev{nullptr}; |
134 | | CoinsCachePair* m_next{nullptr}; |
135 | | uint8_t m_flags{0}; |
136 | | |
137 | | //! Adding a flag requires a reference to the sentinel of the flagged pair linked list. |
138 | | static void AddFlags(uint8_t flags, CoinsCachePair& pair, CoinsCachePair& sentinel) noexcept |
139 | 45.8M | { |
140 | 45.8M | Assume(flags & (DIRTY | FRESH)); |
141 | 45.8M | if (!pair.second.m_flags) { |
142 | 28.6M | Assume(!pair.second.m_prev && !pair.second.m_next); |
143 | 28.6M | pair.second.m_prev = sentinel.second.m_prev; |
144 | 28.6M | pair.second.m_next = &sentinel; |
145 | 28.6M | sentinel.second.m_prev = &pair; |
146 | 28.6M | pair.second.m_prev->second.m_next = &pair; |
147 | 28.6M | } |
148 | 45.8M | Assume(pair.second.m_prev && pair.second.m_next); |
149 | 45.8M | pair.second.m_flags |= flags; |
150 | 45.8M | } |
151 | | |
152 | | public: |
153 | | Coin coin; // The actual cached data. |
154 | | |
155 | | enum Flags { |
156 | | /** |
157 | | * DIRTY means the CCoinsCacheEntry is potentially different from the |
158 | | * version in the parent cache. Failure to mark a coin as DIRTY when |
159 | | * it is potentially different from the parent cache will cause a |
160 | | * consensus failure, since the coin's state won't get written to the |
161 | | * parent when the cache is flushed. |
162 | | */ |
163 | | DIRTY = (1 << 0), |
164 | | /** |
165 | | * FRESH means the parent cache does not have this coin or that it is a |
166 | | * spent coin in the parent cache. If a FRESH coin in the cache is |
167 | | * later spent, it can be deleted entirely and doesn't ever need to be |
168 | | * flushed to the parent. This is a performance optimization. Marking a |
169 | | * coin as FRESH when it exists unspent in the parent cache will cause a |
170 | | * consensus failure, since it might not be deleted from the parent |
171 | | * when this cache is flushed. |
172 | | */ |
173 | | FRESH = (1 << 1), |
174 | | }; |
175 | | |
176 | 56.4M | CCoinsCacheEntry() noexcept = default; |
177 | 24.9k | explicit CCoinsCacheEntry(Coin&& coin_) noexcept : coin(std::move(coin_)) {} |
178 | | ~CCoinsCacheEntry() |
179 | 56.4M | { |
180 | 56.4M | SetClean(); |
181 | 56.4M | } |
182 | | |
183 | 28.6M | static void SetDirty(CoinsCachePair& pair, CoinsCachePair& sentinel) noexcept { AddFlags(DIRTY, pair, sentinel); } |
184 | 17.2M | static void SetFresh(CoinsCachePair& pair, CoinsCachePair& sentinel) noexcept { AddFlags(FRESH, pair, sentinel); } |
185 | | |
186 | | void SetClean() noexcept |
187 | 56.5M | { |
188 | 56.5M | if (!m_flags) return; |
189 | 29.0M | m_next->second.m_prev = m_prev; |
190 | 29.0M | m_prev->second.m_next = m_next; |
191 | 29.0M | m_flags = 0; |
192 | 29.0M | m_prev = m_next = nullptr; |
193 | 29.0M | } |
194 | 31.2M | bool IsDirty() const noexcept { return m_flags & DIRTY; } |
195 | 12.7M | bool IsFresh() const noexcept { return m_flags & FRESH; } |
196 | | |
197 | | //! Only call Next when this entry is DIRTY, FRESH, or both |
198 | | CoinsCachePair* Next() const noexcept |
199 | 1.18M | { |
200 | 1.18M | Assume(m_flags); |
201 | 1.18M | return m_next; |
202 | 1.18M | } |
203 | | |
204 | | //! Only call Prev when this entry is DIRTY, FRESH, or both |
205 | | CoinsCachePair* Prev() const noexcept |
206 | 96.6k | { |
207 | 96.6k | Assume(m_flags); |
208 | 96.6k | return m_prev; |
209 | 96.6k | } |
210 | | |
211 | | //! Only use this for initializing the linked list sentinel |
212 | | void SelfRef(CoinsCachePair& pair) noexcept |
213 | 400k | { |
214 | 400k | Assume(&pair.second == this); |
215 | 400k | m_prev = &pair; |
216 | 400k | m_next = &pair; |
217 | | // Set sentinel to DIRTY so we can call Next on it |
218 | 400k | m_flags = DIRTY; |
219 | 400k | } |
220 | | }; |
221 | | |
222 | | /** |
223 | | * SipHash-1-3-UJ based hasher for the coins cache and related coins containers. |
224 | | * |
225 | | * Retained entries identify real transaction outputs, so their keys contain computed txids. |
226 | | * Missing-input lookups may contain arbitrary claimed prevouts, but FetchCoin() immediately |
227 | | * erases their temporary entries when the backend lookup fails, so non-hash keys cannot |
228 | | * accumulate. |
229 | | * |
230 | | * The assumeutxo loader assumes snapshot txids are valid while loading and verifies the |
231 | | * complete snapshot's content hash before activation. |
232 | | * |
233 | | * Hash values are process-local and must not be persisted, serialized, or compared across |
234 | | * processes. |
235 | | * |
236 | | * Having the hash noexcept lets libstdc++ recalculate it during rehash instead of storing it in |
237 | | * each node. |
238 | | */ |
239 | | class SaltedCoinsCacheHasher |
240 | | { |
241 | | const SipHasher13UJ m_hasher; |
242 | | |
243 | | public: |
244 | | SaltedCoinsCacheHasher(bool deterministic = false); |
245 | | |
246 | | /** Hash a transaction ID, itself a cryptographic hash, as one jumbo block. */ |
247 | | size_t operator()(const Txid& id) const noexcept |
248 | 201k | { |
249 | 201k | return m_hasher.Hash(id.ToUint256()); |
250 | 201k | } |
251 | | |
252 | | /** Hash an outpoint as its txid jumbo block followed by the zero-extended index as one normal block. */ |
253 | | size_t operator()(const COutPoint& id) const noexcept |
254 | 260M | { |
255 | 260M | return m_hasher.Hash(id.hash.ToUint256(), uint64_t{id.n}); |
256 | 260M | } |
257 | | }; |
258 | | |
259 | | /** |
260 | | * PoolAllocator's MAX_BLOCK_SIZE_BYTES parameter here uses sizeof the data, and adds the size |
261 | | * of 4 pointers. We do not know the exact node size used in the std::unordered_node implementation |
262 | | * because it is implementation defined. Most implementations have an overhead of 1 or 2 pointers, |
263 | | * so nodes can be connected in a linked list, and in some cases the hash value is stored as well. |
264 | | * Using an additional sizeof(void*)*4 for MAX_BLOCK_SIZE_BYTES should thus be sufficient so that |
265 | | * all implementations can allocate the nodes from the PoolAllocator. |
266 | | */ |
267 | | using CCoinsMap = std::unordered_map<COutPoint, |
268 | | CCoinsCacheEntry, |
269 | | SaltedCoinsCacheHasher, |
270 | | std::equal_to<COutPoint>, |
271 | | PoolAllocator<CoinsCachePair, |
272 | | sizeof(CoinsCachePair) + sizeof(void*) * 4>>; |
273 | | |
274 | | using CCoinsMapMemoryResource = CCoinsMap::allocator_type::ResourceType; |
275 | | |
276 | | /** Cursor for iterating over CoinsView state */ |
277 | | class CCoinsViewCursor |
278 | | { |
279 | | public: |
280 | 1.24k | CCoinsViewCursor(const uint256& in_block_hash) : block_hash(in_block_hash) {} |
281 | 1.24k | virtual ~CCoinsViewCursor() = default; |
282 | | |
283 | | virtual bool GetKey(COutPoint &key) const = 0; |
284 | | virtual bool GetValue(Coin &coin) const = 0; |
285 | | |
286 | | virtual bool Valid() const = 0; |
287 | | virtual void Next() = 0; |
288 | | |
289 | | //! Get best block at the time this cursor was created |
290 | 102 | const uint256& GetBestBlock() const { return block_hash; } |
291 | | private: |
292 | | uint256 block_hash; |
293 | | }; |
294 | | |
295 | | /** |
296 | | * Cursor for iterating over the linked list of flagged entries in CCoinsViewCache. |
297 | | * |
298 | | * This is a helper struct to encapsulate the diverging logic between a non-erasing |
299 | | * CCoinsViewCache::Sync and an erasing CCoinsViewCache::Flush. This allows the receiver |
300 | | * of CCoinsView::BatchWrite to iterate through the flagged entries without knowing |
301 | | * the caller's intent. |
302 | | * |
303 | | * However, the receiver can still call CoinsViewCacheCursor::WillErase to see if the |
304 | | * caller will erase the entry after BatchWrite returns. If so, the receiver can |
305 | | * perform optimizations such as moving the coin out of the CCoinsCachEntry instead |
306 | | * of copying it. |
307 | | */ |
308 | | struct CoinsViewCacheCursor |
309 | | { |
310 | | //! If will_erase is not set, iterating through the cursor will erase spent coins from the map, |
311 | | //! and other coins will be unflagged (removing them from the linked list). |
312 | | //! If will_erase is set, the underlying map and linked list will not be modified, |
313 | | //! as the caller is expected to wipe the entire map anyway. |
314 | | //! This is an optimization compared to erasing all entries as the cursor iterates them when will_erase is set. |
315 | | //! Calling CCoinsMap::clear() afterwards is faster because a CoinsCachePair cannot be coerced back into a |
316 | | //! CCoinsMap::iterator to be erased, and must therefore be looked up again by key in the CCoinsMap before being erased. |
317 | | CoinsViewCacheCursor(size_t& dirty_count LIFETIMEBOUND, |
318 | | CoinsCachePair& sentinel LIFETIMEBOUND, |
319 | | CCoinsMap& map LIFETIMEBOUND, |
320 | | bool will_erase) noexcept |
321 | 129k | : m_dirty_count(dirty_count), m_sentinel(sentinel), m_map(map), m_will_erase(will_erase) {} |
322 | | |
323 | 129k | inline CoinsCachePair* Begin() const noexcept { return m_sentinel.second.Next(); } |
324 | 1.03M | inline CoinsCachePair* End() const noexcept { return &m_sentinel; } |
325 | | |
326 | | //! Return the next entry after current, possibly erasing current |
327 | | inline CoinsCachePair* NextAndMaybeErase(CoinsCachePair& current) noexcept |
328 | 907k | { |
329 | 907k | const auto next_entry{current.second.Next()}; |
330 | 907k | Assume(TrySub(m_dirty_count, current.second.IsDirty())); |
331 | | // If we are not going to erase the cache, we must still erase spent entries. |
332 | | // Otherwise, clear the state of the entry. |
333 | 907k | if (!m_will_erase) { |
334 | 79.4k | if (current.second.coin.IsSpent()) { |
335 | 21.0k | assert(current.second.coin.DynamicMemoryUsage() == 0); // scriptPubKey was already cleared in SpendCoin |
336 | 21.0k | m_map.erase(current.first); |
337 | 58.3k | } else { |
338 | 58.3k | current.second.SetClean(); |
339 | 58.3k | } |
340 | 79.4k | } |
341 | 907k | return next_entry; |
342 | 907k | } |
343 | | |
344 | 461k | inline bool WillErase(CoinsCachePair& current) const noexcept { return m_will_erase || current.second.coin.IsSpent(); } |
345 | 3.77k | size_t GetDirtyCount() const noexcept { return m_dirty_count; } |
346 | 3.77k | size_t GetTotalCount() const noexcept { return m_map.size(); } |
347 | | private: |
348 | | size_t& m_dirty_count; |
349 | | CoinsCachePair& m_sentinel; |
350 | | CCoinsMap& m_map; |
351 | | bool m_will_erase; |
352 | | }; |
353 | | |
354 | | /** Pure abstract view on the open txout dataset. */ |
355 | | class CCoinsView |
356 | | { |
357 | | public: |
358 | | //! As we use CCoinsViews polymorphically, have a virtual destructor |
359 | 453k | virtual ~CCoinsView() = default; |
360 | | |
361 | | //! Retrieve the Coin (unspent transaction output) for a given outpoint. |
362 | | //! May populate the cache. Use PeekCoin() to perform a non-caching lookup. |
363 | | virtual std::optional<Coin> GetCoin(const COutPoint& outpoint) const = 0; |
364 | | |
365 | | //! Retrieve the Coin (unspent transaction output) for a given outpoint, without caching results. |
366 | | //! Does not populate the cache. Use GetCoin() to cache the result. |
367 | | virtual std::optional<Coin> PeekCoin(const COutPoint& outpoint) const = 0; |
368 | | |
369 | | //! Just check whether a given outpoint is unspent. |
370 | | //! May populate the cache. Use PeekCoin() to perform a non-caching lookup. |
371 | | virtual bool HaveCoin(const COutPoint& outpoint) const = 0; |
372 | | |
373 | | //! Retrieve the block hash whose state this CCoinsView currently represents |
374 | | virtual uint256 GetBestBlock() const = 0; |
375 | | |
376 | | //! Retrieve the range of blocks that may have been only partially written. |
377 | | //! If the database is in a consistent state, the result is the empty vector. |
378 | | //! Otherwise, a two-element vector is returned consisting of the new and |
379 | | //! the old block hash, in that order. |
380 | | virtual std::vector<uint256> GetHeadBlocks() const = 0; |
381 | | |
382 | | //! Do a bulk modification (multiple Coin changes + BestBlock change). |
383 | | //! The passed cursor is used to iterate through the coins. |
384 | | virtual void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& block_hash) = 0; |
385 | | |
386 | | //! Estimate database size |
387 | | virtual size_t EstimateSize() const = 0; |
388 | | }; |
389 | | |
390 | | /** Noop coins view. */ |
391 | | class CoinsViewEmpty : public CCoinsView |
392 | | { |
393 | | protected: |
394 | 4 | CoinsViewEmpty() = default; |
395 | | |
396 | | public: |
397 | | static CoinsViewEmpty& Get(); |
398 | | |
399 | | CoinsViewEmpty(const CoinsViewEmpty&) = delete; |
400 | | CoinsViewEmpty& operator=(const CoinsViewEmpty&) = delete; |
401 | | |
402 | 29 | std::optional<Coin> GetCoin(const COutPoint&) const override { return {}; } |
403 | 1 | std::optional<Coin> PeekCoin(const COutPoint& outpoint) const override { return GetCoin(outpoint); } |
404 | 0 | bool HaveCoin(const COutPoint& outpoint) const override { return !!GetCoin(outpoint); } |
405 | 0 | uint256 GetBestBlock() const override { return {}; } |
406 | 0 | std::vector<uint256> GetHeadBlocks() const override { return {}; } |
407 | | void BatchWrite(CoinsViewCacheCursor& cursor, const uint256&) override |
408 | 0 | { |
409 | 0 | for (auto it{cursor.Begin()}; it != cursor.End(); it = cursor.NextAndMaybeErase(*it)) { } |
410 | 0 | } |
411 | 0 | size_t EstimateSize() const override { return 0; } |
412 | | }; |
413 | | |
414 | | /** CCoinsView backed by another CCoinsView */ |
415 | | class CCoinsViewBacked : public CCoinsView |
416 | | { |
417 | | protected: |
418 | | CCoinsView* base; |
419 | | |
420 | | public: |
421 | 452k | explicit CCoinsViewBacked(CCoinsView* in_view) : base{Assert(in_view)} {} |
422 | | |
423 | 87.8k | void SetBackend(CCoinsView& in_view) { base = &in_view; } |
424 | | |
425 | 914k | std::optional<Coin> GetCoin(const COutPoint& outpoint) const override { return base->GetCoin(outpoint); } |
426 | 399k | std::optional<Coin> PeekCoin(const COutPoint& outpoint) const override { return base->PeekCoin(outpoint); } |
427 | 0 | bool HaveCoin(const COutPoint& outpoint) const override { return base->HaveCoin(outpoint); } |
428 | 44.6k | uint256 GetBestBlock() const override { return base->GetBestBlock(); } |
429 | 0 | std::vector<uint256> GetHeadBlocks() const override { return base->GetHeadBlocks(); } |
430 | 3.46k | void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& block_hash) override { base->BatchWrite(cursor, block_hash); } |
431 | 0 | size_t EstimateSize() const override { return base->EstimateSize(); } |
432 | | }; |
433 | | |
434 | | |
435 | | /** CCoinsView that adds a memory cache for transactions to another CCoinsView */ |
436 | | class CCoinsViewCache : public CCoinsViewBacked |
437 | | { |
438 | | private: |
439 | | const bool m_deterministic; |
440 | | |
441 | | protected: |
442 | | /** |
443 | | * Make mutable so that we can "fill the cache" even from Get-methods |
444 | | * declared as "const". |
445 | | */ |
446 | | mutable uint256 m_block_hash; |
447 | | mutable CCoinsMapMemoryResource m_cache_coins_memory_resource{}; |
448 | | /* The starting sentinel of the flagged entry circular doubly linked list. */ |
449 | | mutable CoinsCachePair m_sentinel; |
450 | | mutable CCoinsMap cacheCoins; |
451 | | |
452 | | /* Cached dynamic memory usage for the inner Coin objects. */ |
453 | | mutable size_t cachedCoinsUsage{0}; |
454 | | /* Running count of dirty Coin cache entries. */ |
455 | | mutable size_t m_dirty_count{0}; |
456 | | |
457 | | /** |
458 | | * Discard all modifications made to this cache without flushing to the base view. |
459 | | * This can be used to efficiently reuse a cache instance across multiple operations. |
460 | | */ |
461 | | virtual void Reset() noexcept; |
462 | | |
463 | | /* Fetch the coin from base. Used for cache misses in FetchCoin. */ |
464 | | virtual std::optional<Coin> FetchCoinFromBase(const COutPoint& outpoint) const; |
465 | | |
466 | | public: |
467 | | CCoinsViewCache(CCoinsView* in_base, bool deterministic = false); |
468 | | |
469 | | /** |
470 | | * By deleting the copy constructor, we prevent accidentally using it when one intends to create a cache on top of a base cache. |
471 | | */ |
472 | | CCoinsViewCache(const CCoinsViewCache &) = delete; |
473 | | |
474 | | // Standard CCoinsView methods |
475 | | std::optional<Coin> GetCoin(const COutPoint& outpoint) const override; |
476 | | std::optional<Coin> PeekCoin(const COutPoint& outpoint) const override; |
477 | | bool HaveCoin(const COutPoint& outpoint) const override; |
478 | | uint256 GetBestBlock() const override; |
479 | | void SetBestBlock(const uint256& block_hash); |
480 | | void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& block_hash) override; |
481 | | |
482 | | /** |
483 | | * Check if we have the given utxo already loaded in this cache. |
484 | | * The semantics are the same as HaveCoin(), but no calls to |
485 | | * the backing CCoinsView are made. |
486 | | */ |
487 | | bool HaveCoinInCache(const COutPoint &outpoint) const; |
488 | | |
489 | | /** |
490 | | * Return a reference to Coin in the cache, or coinEmpty if not found. This is |
491 | | * more efficient than GetCoin. |
492 | | * |
493 | | * Generally, do not hold the reference returned for more than a short scope. |
494 | | * While the current implementation allows for modifications to the contents |
495 | | * of the cache while holding the reference, this behavior should not be relied |
496 | | * on! To be safe, best to not hold the returned reference through any other |
497 | | * calls to this cache. |
498 | | */ |
499 | | const Coin& AccessCoin(const COutPoint &output) const; |
500 | | |
501 | | /** |
502 | | * Add a coin. Set possible_overwrite to true if an unspent version may |
503 | | * already exist in the cache. |
504 | | */ |
505 | | void AddCoin(const COutPoint& outpoint, Coin&& coin, bool possible_overwrite); |
506 | | |
507 | | /** |
508 | | * Emplace a coin into cacheCoins without performing any checks, marking |
509 | | * the emplaced coin as dirty. |
510 | | * |
511 | | * NOT FOR GENERAL USE. Used only when loading coins from a UTXO snapshot. |
512 | | * @sa ChainstateManager::PopulateAndValidateSnapshot() |
513 | | */ |
514 | | void EmplaceCoinInternalDANGER(const COutPoint& outpoint, Coin&& coin); |
515 | | |
516 | | /** |
517 | | * Spend a coin. Pass moveto in order to get the deleted data. |
518 | | * If no unspent output exists for the passed outpoint, this call |
519 | | * has no effect. |
520 | | */ |
521 | | bool SpendCoin(const COutPoint &outpoint, Coin* moveto = nullptr); |
522 | | |
523 | | /** |
524 | | * Push the modifications applied to this cache to its base and wipe local state. |
525 | | * Failure to call this method or Sync() before destruction will cause the changes |
526 | | * to be forgotten. |
527 | | * If reallocate_cache is false, the cache will retain the same memory footprint |
528 | | * after flushing and should be destroyed to deallocate. |
529 | | */ |
530 | | virtual void Flush(bool reallocate_cache = true); |
531 | | |
532 | | /** |
533 | | * Push the modifications applied to this cache to its base while retaining |
534 | | * the contents of this cache (except for spent coins, which we erase). |
535 | | * Failure to call this method or Flush() before destruction will cause the changes |
536 | | * to be forgotten. |
537 | | */ |
538 | | void Sync(); |
539 | | |
540 | | /** |
541 | | * Removes the UTXO with the given outpoint from the cache, if it is |
542 | | * not modified. |
543 | | */ |
544 | | void Uncache(const COutPoint &outpoint); |
545 | | |
546 | | //! Size of the cache (in number of transaction outputs) |
547 | | unsigned int GetCacheSize() const; |
548 | | |
549 | | //! Number of dirty cache entries (transaction outputs) |
550 | 3.44k | size_t GetDirtyCount() const noexcept { return m_dirty_count; } |
551 | | |
552 | | //! Calculate the size of the cache (in bytes) |
553 | | size_t DynamicMemoryUsage() const; |
554 | | |
555 | | //! Check whether all prevouts of the transaction are present in the UTXO set represented by this view |
556 | | bool HaveInputs(const CTransaction& tx) const; |
557 | | |
558 | | //! Force a reallocation of the cache map. This is required when downsizing |
559 | | //! the cache because the map's allocator may be hanging onto a lot of |
560 | | //! memory despite having called .clear(). |
561 | | //! |
562 | | //! See: https://stackoverflow.com/questions/42114044/how-to-release-unordered-map-memory |
563 | | void ReallocateCache(); |
564 | | |
565 | | //! Run an internal sanity check on the cache data structure. */ |
566 | | void SanityCheck() const; |
567 | | |
568 | | class ResetGuard |
569 | | { |
570 | | private: |
571 | | friend CCoinsViewCache; |
572 | | CCoinsViewCache& m_cache; |
573 | 113k | explicit ResetGuard(CCoinsViewCache& cache LIFETIMEBOUND) noexcept : m_cache{cache} {} |
574 | | |
575 | | public: |
576 | | ResetGuard(const ResetGuard&) = delete; |
577 | | ResetGuard& operator=(const ResetGuard&) = delete; |
578 | | ResetGuard(ResetGuard&&) = delete; |
579 | | ResetGuard& operator=(ResetGuard&&) = delete; |
580 | | |
581 | 113k | ~ResetGuard() { m_cache.Reset(); } |
582 | | }; |
583 | | |
584 | | //! Create a scoped guard that will call `Reset()` on this cache when it goes out of scope. |
585 | 113k | [[nodiscard]] ResetGuard CreateResetGuard() noexcept { return ResetGuard{*this}; } |
586 | | |
587 | | private: |
588 | | /** |
589 | | * @note this is marked const, but may actually append to `cacheCoins`, increasing |
590 | | * memory usage. |
591 | | */ |
592 | | CCoinsMap::iterator FetchCoin(const COutPoint &outpoint) const; |
593 | | }; |
594 | | |
595 | | /** |
596 | | * CCoinsViewCache subclass that asynchronously fetches most block input prevouts in parallel during ConnectBlock without |
597 | | * mutating the base cache. |
598 | | * |
599 | | * Only used in ConnectBlock to pass as an ephemeral view that can be reset if the block is invalid. |
600 | | * It provides the same interface as CCoinsViewCache. |
601 | | * It adds an additional StartFetching method to provide the block. |
602 | | * |
603 | | * When a block is passed to StartFetching, the inputs of the block are flattened into a vector of InputToFetch |
604 | | * objects. StartFetching then submits worker tasks to a ThreadPool and keeps the returned futures alive until fetching |
605 | | * is stopped. |
606 | | * |
607 | | * ProcessInput() atomically fetches and increments m_input_head, so each thread can only access a single element of the |
608 | | * m_inputs vector at a time. Workers race to claim inputs, so they may fetch elements in any order. If the fetched |
609 | | * index is greater than or equal to the size of m_inputs, no more inputs can be fetched and false is returned. |
610 | | * |
611 | | * The worker claims the InputToFetch at this index, fetches the coin from the base cache and moves it into the |
612 | | * InputToFetch object. The ready flag is then set with a release memory order. This allows the ready flag to be |
613 | | * used as a memory fence, guaranteeing the coin being written to the object will have happened before another |
614 | | * thread tests the flag with an acquire memory order. |
615 | | * This assumes all base->PeekCoin() paths are safe for concurrent readers and do not mutate lower cache layers. |
616 | | * |
617 | | * When a coin is requested from the cache on the main thread and is not already in cacheCoins map, FetchCoinFromBase |
618 | | * checks whether the next unconsumed entry in m_inputs has the requested outpoint. On a match, m_input_tail is advanced |
619 | | * and the entry's ready flag is waited on with an acquire memory order until a worker has finished fetching it. The |
620 | | * coin is then moved out and returned. Since the main thread is the only consumer of validation results, it blocks |
621 | | * on the specific input it needs rather than racing workers for other inputs. |
622 | | * |
623 | | * StopFetching() is called in Flush() and in Reset() (the per-block teardown) so workers stop before the block they |
624 | | * reference goes away. It stops fetching by moving m_input_head to the end of m_inputs (so workers quickly exit), |
625 | | * then waits for all futures to complete and clears the per-block state (m_inputs and the head/tail counters). |
626 | | * |
627 | | * Workers advance m_input_head to fetch inputs. Main thread advances m_input_tail to consume. |
628 | | * |
629 | | * Before workers start: |
630 | | * |
631 | | * m_input_head |
632 | | * m_input_tail |
633 | | * │ |
634 | | * ▼ |
635 | | * ┌─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐ |
636 | | * m_inputs: │ waiting │ waiting │ waiting │ waiting │ waiting │ waiting │ waiting │ waiting │ waiting │ |
637 | | * │ │ │ │ │ │ │ │ │ │ |
638 | | * └─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘ |
639 | | * |
640 | | * After workers start: |
641 | | * |
642 | | * Worker 2 Worker 0 Worker 3 Worker 1 m_input_head |
643 | | * │ │ │ │ │ |
644 | | * ▼ ▼ ▼ ▼ ▼ |
645 | | * ┌─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐ |
646 | | * m_inputs: │ ready │ ready │fetching │ ready │fetching │fetching │fetching │ waiting │ waiting │ |
647 | | * │consumed │ ✓ │ ● │ ✓ │ ● │ ● │ ● │ │ │ |
648 | | * └─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘ |
649 | | * ▲ |
650 | | * │ |
651 | | * m_input_tail |
652 | | */ |
653 | | class CoinsViewOverlay : public CCoinsViewCache |
654 | | { |
655 | | private: |
656 | | //! The latest input not yet being fetched. Workers atomically increment this when fetching. |
657 | | std::atomic_uint32_t m_input_head{0}; |
658 | | //! The latest input not yet accessed by a consumer. Only the main thread increments this. |
659 | | mutable uint32_t m_input_tail{0}; |
660 | | |
661 | | //! The inputs of the block which is being fetched. |
662 | | struct InputToFetch { |
663 | | //! Workers set this after setting the coin. The main thread tests this before reading the coin. |
664 | | std::atomic_flag ready{}; |
665 | | //! The outpoint of the input to fetch. |
666 | | const COutPoint& outpoint; |
667 | | //! The coin that workers will fetch and main thread will insert into cache. |
668 | | //! Mutable so it can be moved in FetchCoinFromBase. |
669 | | mutable std::optional<Coin> coin{std::nullopt}; |
670 | | |
671 | 52.2k | explicit InputToFetch(const COutPoint& o LIFETIMEBOUND) noexcept : outpoint{o} {} |
672 | | |
673 | | //! Move ctor is required for resizing m_inputs in StartFetching. Elements will never move once parallel tasks |
674 | | //! are started, so we can assert that coin is nullopt and ready is false. |
675 | 14.5k | InputToFetch(InputToFetch&& other) noexcept : outpoint{other.outpoint} |
676 | 14.5k | { |
677 | 14.5k | Assert(!other.coin); |
678 | 14.5k | Assert(!other.ready.test(std::memory_order_relaxed)); |
679 | 14.5k | } |
680 | | }; |
681 | | //! Must only be mutated when m_futures is empty. Elements may be mutated when m_futures is not empty. |
682 | | std::vector<InputToFetch> m_inputs{}; |
683 | | |
684 | | /** |
685 | | * Claim and fetch the next input in the queue. |
686 | | * |
687 | | * @return true if an input prevout was fetched |
688 | | * @return false if there are no more input prevouts in the queue to fetch |
689 | | */ |
690 | | bool ProcessInput() noexcept |
691 | 77.1k | { |
692 | 77.1k | const auto i{m_input_head.fetch_add(1, std::memory_order_relaxed)}; |
693 | 77.1k | if (i >= m_inputs.size()) return false; |
694 | | |
695 | 51.9k | auto& input{m_inputs[i]}; |
696 | 51.9k | input.coin = base->PeekCoin(input.outpoint); |
697 | | // Use release so writing coin above happens before the main thread acquires. |
698 | 51.9k | Assert(!input.ready.test_and_set(std::memory_order_release)); |
699 | 51.9k | input.ready.notify_one(); |
700 | 51.9k | return true; |
701 | 77.1k | } |
702 | | |
703 | | //! Stop all worker threads and clear fetching data. |
704 | | //! Calling this is idempotent, and may safely be called if not fetching. |
705 | | void StopFetching() noexcept |
706 | 226k | { |
707 | 226k | if (m_futures.empty()) { |
708 | 217k | Assert(m_inputs.empty()); |
709 | 217k | Assert(m_input_head.load(std::memory_order_relaxed) == 0); |
710 | 217k | Assert(m_input_tail == 0); |
711 | 217k | return; |
712 | 217k | } |
713 | | // Skip fetching the rest of the inputs by moving the head to the end. |
714 | 9.21k | m_input_head.store(m_inputs.size(), std::memory_order_relaxed); |
715 | | // Wait for all threads to stop. |
716 | 25.1k | for (auto& future : m_futures) future.wait(); |
717 | 9.21k | m_futures.clear(); |
718 | 9.21k | m_inputs.clear(); |
719 | 9.21k | m_input_head.store(0, std::memory_order_relaxed); |
720 | 9.21k | m_input_tail = 0; |
721 | 9.21k | } |
722 | | |
723 | | std::optional<Coin> FetchCoinFromBase(const COutPoint& outpoint) const override |
724 | 454k | { |
725 | | // This assumes ConnectBlock accesses all inputs in the same order as |
726 | | // they are added to m_inputs in StartFetching. |
727 | 454k | if (m_input_tail < m_inputs.size() && m_inputs[m_input_tail].outpoint == outpoint) { |
728 | | // We advance the tail since the input is cached and not accessed through this method again. |
729 | 52.0k | auto& input{m_inputs[m_input_tail++]}; |
730 | | // Wait until the coin is ready to be read. We need acquire so we match the worker thread's release. |
731 | 52.0k | input.ready.wait(/*old=*/false, std::memory_order_acquire); |
732 | | // We can move the coin since we won't access this input again. |
733 | 52.0k | return std::move(input.coin); |
734 | 52.0k | } |
735 | | |
736 | | // We will only get here for BIP30 checks, an invalid block, or if the threadpool has not been started. |
737 | 402k | return base->PeekCoin(outpoint); |
738 | 454k | } |
739 | | |
740 | | //! Non-null. May have zero workers when input fetching is disabled. |
741 | | std::shared_ptr<ThreadPool> m_thread_pool; |
742 | | std::vector<std::future<void>> m_futures{}; |
743 | | |
744 | | protected: |
745 | | void Reset() noexcept override |
746 | 113k | { |
747 | 113k | StopFetching(); |
748 | 113k | CCoinsViewCache::Reset(); |
749 | 113k | } |
750 | | |
751 | | public: |
752 | | explicit CoinsViewOverlay(CCoinsView* in_base, std::shared_ptr<ThreadPool> thread_pool, |
753 | | bool deterministic = false) noexcept |
754 | 1.26k | : CCoinsViewCache{in_base, deterministic}, m_thread_pool{std::move(thread_pool)} |
755 | 1.26k | { |
756 | 1.26k | Assert(m_thread_pool); |
757 | 1.26k | } |
758 | | |
759 | 1.26k | ~CoinsViewOverlay() noexcept override { StopFetching(); } |
760 | | |
761 | | //! Start fetching inputs from block. |
762 | | [[nodiscard]] ResetGuard StartFetching(const CBlock& block LIFETIMEBOUND) noexcept; |
763 | | |
764 | | void Flush(bool reallocate_cache = true) override |
765 | 111k | { |
766 | 111k | if (!Assume(AllInputsConsumed())) { |
767 | 0 | LogWarning("Block %s input prevout prefetch queue was not fully consumed; inputs were accessed out of order, so prefetching degraded to serial lookups for this block.", GetBestBlock().ToString()); |
768 | 0 | } |
769 | 111k | StopFetching(); |
770 | 111k | CCoinsViewCache::Flush(reallocate_cache); |
771 | 111k | } |
772 | | |
773 | | //! Verify that all parallel fetched input prevouts have been consumed. |
774 | 111k | bool AllInputsConsumed() const noexcept { return m_input_tail == m_inputs.size(); } |
775 | | }; |
776 | | |
777 | | //! Utility function to add all of a transaction's outputs to a cache. |
778 | | //! When check is false, this assumes that overwrites are only possible for coinbase transactions. |
779 | | //! When check is true, the underlying view may be queried to determine whether an addition is |
780 | | //! an overwrite. |
781 | | // TODO: pass in a boolean to limit these possible overwrites to known |
782 | | // (pre-BIP34) cases. |
783 | | void AddCoins(CCoinsViewCache& cache, const CTransaction& tx, int nHeight, bool check = false); |
784 | | |
785 | | //! Utility function to find any unspent output with a given txid. |
786 | | //! This function can be quite expensive because in the event of a transaction |
787 | | //! which is not found in the cache, it can cause up to MAX_OUTPUTS_PER_BLOCK |
788 | | //! lookups to database, so it should be used with care. |
789 | | const Coin& AccessByTxid(const CCoinsViewCache& cache, const Txid& txid); |
790 | | |
791 | | /** |
792 | | * This is a minimally invasive approach to shutdown on LevelDB read errors from the |
793 | | * chainstate, while keeping user interface out of the common library, which is shared |
794 | | * between bitcoind, and bitcoin-qt and non-server tools. |
795 | | * |
796 | | * Writes do not need similar protection, as failure to write is handled by the caller. |
797 | | */ |
798 | | class CCoinsViewErrorCatcher final : public CCoinsViewBacked |
799 | | { |
800 | | public: |
801 | 1.25k | explicit CCoinsViewErrorCatcher(CCoinsView* view) : CCoinsViewBacked(view) {} |
802 | | |
803 | 1.04k | void AddReadErrCallback(std::function<void()> f) { |
804 | 1.04k | m_err_callbacks.emplace_back(std::move(f)); |
805 | 1.04k | } |
806 | | |
807 | | std::optional<Coin> GetCoin(const COutPoint& outpoint) const override; |
808 | | bool HaveCoin(const COutPoint& outpoint) const override; |
809 | | std::optional<Coin> PeekCoin(const COutPoint& outpoint) const override; |
810 | | |
811 | | private: |
812 | | /** A list of callbacks to execute upon leveldb read error. */ |
813 | | std::vector<std::function<void()>> m_err_callbacks; |
814 | | |
815 | | }; |
816 | | |
817 | | #endif // BITCOIN_COINS_H |