Bitcoin ABC 0.32.6
P2P Digital Currency
coins.cpp
Go to the documentation of this file.
1// Copyright (c) 2012-2016 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <coins.h>
6
8#include <logging.h>
9#include <random.h>
10#include <util/trace.h>
11
12bool CCoinsView::GetCoin(const COutPoint &outpoint, Coin &coin) const {
13 return false;
14}
16 return BlockHash();
17}
18std::vector<BlockHash> CCoinsView::GetHeadBlocks() const {
19 return std::vector<BlockHash>();
20}
22 const BlockHash &hashBlock) {
23 return false;
24}
26 return nullptr;
27}
28bool CCoinsView::HaveCoin(const COutPoint &outpoint) const {
29 Coin coin;
30 return GetCoin(outpoint, coin);
31}
32
34bool CCoinsViewBacked::GetCoin(const COutPoint &outpoint, Coin &coin) const {
35 return base->GetCoin(outpoint, coin);
36}
37bool CCoinsViewBacked::HaveCoin(const COutPoint &outpoint) const {
38 return base->HaveCoin(outpoint);
39}
41 return base->GetBestBlock();
42}
43std::vector<BlockHash> CCoinsViewBacked::GetHeadBlocks() const {
44 return base->GetHeadBlocks();
45}
47 base = &viewIn;
48}
50 const BlockHash &hashBlock) {
51 return base->BatchWrite(cursor, hashBlock);
52}
54 return base->Cursor();
55}
57 return base->EstimateSize();
58}
59
60CCoinsViewCache::CCoinsViewCache(CCoinsView *baseIn, bool deterministic)
61 : CCoinsViewBacked(baseIn), m_deterministic(deterministic),
62 cacheCoins(0, SaltedOutpointHasher(/*deterministic=*/deterministic),
63 CCoinsMap::key_equal{}, &m_cache_coins_memory_resource),
64 cachedCoinsUsage(0) {
65 m_sentinel.second.SelfRef(m_sentinel);
66}
67
70}
71
72CCoinsMap::iterator
73CCoinsViewCache::FetchCoin(const COutPoint &outpoint) const {
74 const auto [ret, inserted] = cacheCoins.try_emplace(outpoint);
75 if (inserted) {
76 if (!base->GetCoin(outpoint, ret->second.coin)) {
77 cacheCoins.erase(ret);
78 return cacheCoins.end();
79 }
80 if (ret->second.coin.IsSpent()) {
81 // The parent only has an empty entry for this outpoint; we can
82 // consider our version as fresh.
84 }
85 cachedCoinsUsage += ret->second.coin.DynamicMemoryUsage();
86 }
87 return ret;
88}
89
90bool CCoinsViewCache::GetCoin(const COutPoint &outpoint, Coin &coin) const {
91 CCoinsMap::const_iterator it = FetchCoin(outpoint);
92 if (it == cacheCoins.end()) {
93 return false;
94 }
95 coin = it->second.coin;
96 return !coin.IsSpent();
97}
98
99void CCoinsViewCache::AddCoin(const COutPoint &outpoint, Coin coin,
100 bool possible_overwrite) {
101 assert(!coin.IsSpent());
102 if (coin.GetTxOut().scriptPubKey.IsUnspendable()) {
103 return;
104 }
105 CCoinsMap::iterator it;
106 bool inserted;
107 std::tie(it, inserted) =
108 cacheCoins.emplace(std::piecewise_construct,
109 std::forward_as_tuple(outpoint), std::tuple<>());
110 bool fresh = false;
111 if (!inserted) {
112 cachedCoinsUsage -= it->second.coin.DynamicMemoryUsage();
113 }
114 if (!possible_overwrite) {
115 if (!it->second.coin.IsSpent()) {
116 throw std::logic_error("Attempted to overwrite an unspent coin "
117 "(when possible_overwrite is false)");
118 }
119 // If the coin exists in this cache as a spent coin and is DIRTY, then
120 // its spentness hasn't been flushed to the parent cache. We're
121 // re-adding the coin to this cache now but we can't mark it as FRESH.
122 // If we mark it FRESH and then spend it before the cache is flushed
123 // we would remove it from this cache and would never flush spentness
124 // to the parent cache.
125 //
126 // Re-adding a spent coin can happen in the case of a re-org (the coin
127 // is 'spent' when the block adding it is disconnected and then
128 // re-added when it is also added in a newly connected block).
129 //
130 // If the coin doesn't exist in the current cache, or is spent but not
131 // DIRTY, then it can be marked FRESH.
132 fresh = !it->second.IsDirty();
133 }
134 it->second.coin = std::move(coin);
136 if (fresh) {
138 }
139 cachedCoinsUsage += it->second.coin.DynamicMemoryUsage();
140 TRACE5(utxocache, add, outpoint.GetTxId().data(), outpoint.GetN(),
141 coin.GetHeight(), coin.GetTxOut().nValue.ToString().c_str(),
142 coin.IsCoinBase());
143}
144
146 Coin &&coin) {
147 cachedCoinsUsage += coin.DynamicMemoryUsage();
148 auto [it, inserted] =
149 cacheCoins.try_emplace(std::move(outpoint), std::move(coin));
150 if (inserted) {
152 }
153}
154
155void AddCoins(CCoinsViewCache &cache, const CTransaction &tx, int nHeight,
156 bool check_for_overwrite) {
157 bool fCoinbase = tx.IsCoinBase();
158 const TxId txid = tx.GetId();
159 for (size_t i = 0; i < tx.vout.size(); ++i) {
160 const COutPoint outpoint(txid, i);
161 bool overwrite =
162 check_for_overwrite ? cache.HaveCoin(outpoint) : fCoinbase;
163 // Coinbase transactions can always be overwritten,
164 // in order to correctly deal with the pre-BIP30 occurrences of
165 // duplicate coinbase transactions.
166 cache.AddCoin(outpoint, Coin(tx.vout[i], nHeight, fCoinbase),
167 overwrite);
168 }
169}
170
171bool CCoinsViewCache::SpendCoin(const COutPoint &outpoint, Coin *moveout) {
172 CCoinsMap::iterator it = FetchCoin(outpoint);
173 if (it == cacheCoins.end()) {
174 return false;
175 }
176 cachedCoinsUsage -= it->second.coin.DynamicMemoryUsage();
177 TRACE5(utxocache, spent, outpoint.GetTxId().data(), outpoint.GetN(),
178 it->second.coin.GetHeight(),
179 it->second.coin.GetTxOut().nValue.ToString().c_str(),
180 it->second.coin.IsCoinBase());
181 if (moveout) {
182 *moveout = std::move(it->second.coin);
183 }
184 if (it->second.IsFresh()) {
185 cacheCoins.erase(it);
186 } else {
188 it->second.coin.Clear();
189 }
190 return true;
191}
192
193static const Coin coinEmpty;
194
195const Coin &CCoinsViewCache::AccessCoin(const COutPoint &outpoint) const {
196 CCoinsMap::const_iterator it = FetchCoin(outpoint);
197 if (it == cacheCoins.end()) {
198 return coinEmpty;
199 }
200 return it->second.coin;
201}
202
203bool CCoinsViewCache::HaveCoin(const COutPoint &outpoint) const {
204 CCoinsMap::const_iterator it = FetchCoin(outpoint);
205 return it != cacheCoins.end() && !it->second.coin.IsSpent();
206}
207
208bool CCoinsViewCache::HaveCoinInCache(const COutPoint &outpoint) const {
209 CCoinsMap::const_iterator it = cacheCoins.find(outpoint);
210 return (it != cacheCoins.end() && !it->second.coin.IsSpent());
211}
212
214 if (hashBlock.IsNull()) {
216 }
217 return hashBlock;
218}
219
220void CCoinsViewCache::SetBestBlock(const BlockHash &hashBlockIn) {
221 hashBlock = hashBlockIn;
222}
223
225 const BlockHash &hashBlockIn) {
226 for (auto it{cursor.Begin()}; it != cursor.End();
227 it = cursor.NextAndMaybeErase(*it)) {
228 // Ignore non-dirty entries (optimization).
229 if (!it->second.IsDirty()) {
230 continue;
231 }
232 CCoinsMap::iterator itUs = cacheCoins.find(it->first);
233 if (itUs == cacheCoins.end()) {
234 // The parent cache does not have an entry, while the child cache
235 // does. We can ignore it if it's both spent and FRESH in the child
236 if (!(it->second.IsFresh() && it->second.coin.IsSpent())) {
237 // Create the coin in the parent cache, move the data up
238 // and mark it as dirty.
239 itUs = cacheCoins.try_emplace(it->first).first;
240 CCoinsCacheEntry &entry{itUs->second};
241
242 if (cursor.WillErase(*it)) {
243 // Since this entry will be erased,
244 // we can move the coin into us instead of copying it
245 entry.coin = std::move(it->second.coin);
246 } else {
247 entry.coin = it->second.coin;
248 }
249 cachedCoinsUsage += entry.coin.DynamicMemoryUsage();
251 // We can mark it FRESH in the parent if it was FRESH in the
252 // child. Otherwise it might have just been flushed from the
253 // parent's cache and already exist in the grandparent
254 if (it->second.IsFresh()) {
256 }
257 }
258 } else {
259 // Found the entry in the parent cache
260 if (it->second.IsFresh() && !itUs->second.coin.IsSpent()) {
261 // The coin was marked FRESH in the child cache, but the coin
262 // exists in the parent cache. If this ever happens, it means
263 // the FRESH flag was misapplied and there is a logic error in
264 // the calling code.
265 throw std::logic_error("FRESH flag misapplied to coin that "
266 "exists in parent cache");
267 }
268
269 if (itUs->second.IsFresh() && it->second.coin.IsSpent()) {
270 // The grandparent cache does not have an entry, and the coin
271 // has been spent. We can just delete it from the parent cache.
272 cachedCoinsUsage -= itUs->second.coin.DynamicMemoryUsage();
273 cacheCoins.erase(itUs);
274 } else {
275 // A normal modification.
276 cachedCoinsUsage -= itUs->second.coin.DynamicMemoryUsage();
277 if (cursor.WillErase(*it)) {
278 // Since this entry will be erased,
279 // we can move the coin into us instead of copying it
280 itUs->second.coin = std::move(it->second.coin);
281 } else {
282 itUs->second.coin = it->second.coin;
283 }
284 cachedCoinsUsage += itUs->second.coin.DynamicMemoryUsage();
286 // NOTE: It isn't safe to mark the coin as FRESH in the parent
287 // cache. If it already existed and was spent in the parent
288 // cache then marking it FRESH would prevent that spentness
289 // from being flushed to the grandparent.
290 }
291 }
292 }
293 hashBlock = hashBlockIn;
294 return true;
295}
296
299 /*will_erase=*/true)};
300 bool fOk = base->BatchWrite(cursor, hashBlock);
301 if (fOk) {
302 cacheCoins.clear();
304 }
306 return fOk;
307}
308
311 /*will_erase=*/false)};
312 bool fOk = base->BatchWrite(cursor, hashBlock);
313 if (fOk) {
314 if (m_sentinel.second.Next() != &m_sentinel) {
315 /* BatchWrite must clear flags of all entries */
316 throw std::logic_error(
317 "Not all unspent flagged entries were cleared");
318 }
319 }
320 return fOk;
321}
322
323void CCoinsViewCache::Uncache(const COutPoint &outpoint) {
324 CCoinsMap::iterator it = cacheCoins.find(outpoint);
325 if (it != cacheCoins.end() && !it->second.IsDirty() &&
326 !it->second.IsFresh()) {
327 cachedCoinsUsage -= it->second.coin.DynamicMemoryUsage();
328 TRACE5(utxocache, uncache, outpoint.GetTxId().data(), outpoint.GetN(),
329 it->second.coin.GetHeight(),
330 it->second.coin.GetTxOut().nValue.ToString().c_str(),
331 it->second.coin.IsCoinBase());
332 cacheCoins.erase(it);
333 }
334}
335
336unsigned int CCoinsViewCache::GetCacheSize() const {
337 return cacheCoins.size();
338}
339
340bool CCoinsViewCache::HaveInputs(const CTransaction &tx) const {
341 if (tx.IsCoinBase()) {
342 return true;
343 }
344
345 for (size_t i = 0; i < tx.vin.size(); i++) {
346 if (!HaveCoin(tx.vin[i].prevout)) {
347 return false;
348 }
349 }
350
351 return true;
352}
353
355 // Cache should be empty when we're calling this.
356 assert(cacheCoins.size() == 0);
357 cacheCoins.~CCoinsMap();
358 m_cache_coins_memory_resource.~CCoinsMapMemoryResource();
360 ::new (&cacheCoins)
361 CCoinsMap{0, SaltedOutpointHasher{/*deterministic=*/m_deterministic},
362 CCoinsMap::key_equal{}, &m_cache_coins_memory_resource};
363}
364
366 size_t recomputed_usage = 0;
367 size_t count_flagged = 0;
368 for (const auto &[_, entry] : cacheCoins) {
369 unsigned attr = 0;
370 if (entry.IsDirty()) {
371 attr |= 1;
372 }
373 if (entry.IsFresh()) {
374 attr |= 2;
375 }
376 if (entry.coin.IsSpent()) {
377 attr |= 4;
378 }
379 // Only 5 combinations are possible.
380 assert(attr != 2 && attr != 4 && attr != 7);
381
382 // Recompute cachedCoinsUsage.
383 recomputed_usage += entry.coin.DynamicMemoryUsage();
384
385 // Count the number of entries we expect in the linked list.
386 if (entry.IsDirty() || entry.IsFresh()) {
387 ++count_flagged;
388 }
389 }
390 // Iterate over the linked list of flagged entries.
391 size_t count_linked = 0;
392 for (auto it = m_sentinel.second.Next(); it != &m_sentinel;
393 it = it->second.Next()) {
394 // Verify linked list integrity.
395 assert(it->second.Next()->second.Prev() == it);
396 assert(it->second.Prev()->second.Next() == it);
397 // Verify they are actually flagged.
398 assert(it->second.IsDirty() || it->second.IsFresh());
399 // Count the number of entries actually in the list.
400 ++count_linked;
401 }
402 assert(count_linked == count_flagged);
403 assert(recomputed_usage == cachedCoinsUsage);
404}
405
406// TODO: merge with similar definition in undo.h.
407static const size_t MAX_OUTPUTS_PER_TX =
409
410const Coin &AccessByTxid(const CCoinsViewCache &view, const TxId &txid) {
411 for (uint32_t n = 0; n < MAX_OUTPUTS_PER_TX; n++) {
412 const Coin &alternate = view.AccessCoin(COutPoint(txid, n));
413 if (!alternate.IsSpent()) {
414 return alternate;
415 }
416 }
417
418 return coinEmpty;
419}
420
421bool CCoinsViewErrorCatcher::GetCoin(const COutPoint &outpoint,
422 Coin &coin) const {
423 try {
424 return CCoinsViewBacked::GetCoin(outpoint, coin);
425 } catch (const std::runtime_error &e) {
426 for (const auto &f : m_err_callbacks) {
427 f();
428 }
429 LogPrintf("Error reading from database: %s\n", e.what());
430 // Starting the shutdown sequence and returning false to the caller
431 // would be interpreted as 'entry not found' (as opposed to unable to
432 // read data), and could lead to invalid interpretation. Just exit
433 // immediately, as we can't continue anyway, and all writes should be
434 // atomic.
435 std::abort();
436 }
437}
CCoinsView backed by another CCoinsView.
Definition: coins.h:343
bool HaveCoin(const COutPoint &outpoint) const override
Just check whether a given outpoint is unspent.
Definition: coins.cpp:37
BlockHash GetBestBlock() const override
Retrieve the block hash whose state this CCoinsView currently represents.
Definition: coins.cpp:40
CCoinsViewCursor * Cursor() const override
Get a cursor to iterate over the whole state.
Definition: coins.cpp:53
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
Definition: coins.cpp:34
size_t EstimateSize() const override
Estimate database size (0 if not implemented)
Definition: coins.cpp:56
void SetBackend(CCoinsView &viewIn)
Definition: coins.cpp:46
CCoinsView * base
Definition: coins.h:345
std::vector< BlockHash > GetHeadBlocks() const override
Retrieve the range of blocks that may have been only partially written.
Definition: coins.cpp:43
bool BatchWrite(CoinsViewCacheCursor &cursor, const BlockHash &hashBlock) override
Do a bulk modification (multiple Coin changes + BestBlock change).
Definition: coins.cpp:49
CCoinsViewBacked(CCoinsView *viewIn)
Definition: coins.cpp:33
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Definition: coins.h:363
CCoinsViewCache(CCoinsView *baseIn, bool deterministic=false)
Definition: coins.cpp:60
void AddCoin(const COutPoint &outpoint, Coin coin, bool possible_overwrite)
Add a coin.
Definition: coins.cpp:99
const bool m_deterministic
Definition: coins.h:365
BlockHash GetBestBlock() const override
Retrieve the block hash whose state this CCoinsView currently represents.
Definition: coins.cpp:213
CCoinsMapMemoryResource m_cache_coins_memory_resource
Definition: coins.h:373
bool SpendCoin(const COutPoint &outpoint, Coin *moveto=nullptr)
Spend a coin.
Definition: coins.cpp:171
void Uncache(const COutPoint &outpoint)
Removes the UTXO with the given outpoint from the cache, if it is not modified.
Definition: coins.cpp:323
bool HaveInputs(const CTransaction &tx) const
Check whether all prevouts of the transaction are present in the UTXO set represented by this view.
Definition: coins.cpp:340
bool BatchWrite(CoinsViewCacheCursor &cursor, const BlockHash &hashBlock) override
Do a bulk modification (multiple Coin changes + BestBlock change).
Definition: coins.cpp:224
void SetBestBlock(const BlockHash &hashBlock)
Definition: coins.cpp:220
BlockHash hashBlock
Make mutable so that we can "fill the cache" even from Get-methods declared as "const".
Definition: coins.h:372
unsigned int GetCacheSize() const
Calculate the size of the cache (in number of transaction outputs)
Definition: coins.cpp:336
size_t cachedCoinsUsage
Definition: coins.h:381
CCoinsMap::iterator FetchCoin(const COutPoint &outpoint) const
Definition: coins.cpp:73
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
Definition: coins.cpp:90
bool HaveCoinInCache(const COutPoint &outpoint) const
Check if we have the given utxo already loaded in this cache.
Definition: coins.cpp:208
bool Flush()
Push the modifications applied to this cache to its base and wipe local state.
Definition: coins.cpp:297
CoinsCachePair m_sentinel
The starting sentinel of the flagged entry circular doubly linked list.
Definition: coins.h:377
size_t DynamicMemoryUsage() const
Calculate the size of the cache (in bytes)
Definition: coins.cpp:68
bool Sync()
Push the modifications applied to this cache to its base while retaining the contents of this cache (...
Definition: coins.cpp:309
void EmplaceCoinInternalDANGER(COutPoint &&outpoint, Coin &&coin)
Emplace a coin into cacheCoins without performing any checks, marking the emplaced coin as dirty.
Definition: coins.cpp:145
bool HaveCoin(const COutPoint &outpoint) const override
Just check whether a given outpoint is unspent.
Definition: coins.cpp:203
void SanityCheck() const
Run an internal sanity check on the cache data structure.
Definition: coins.cpp:365
CCoinsMap cacheCoins
Definition: coins.h:378
const Coin & AccessCoin(const COutPoint &output) const
Return a reference to Coin in the cache, or coinEmpty if not found.
Definition: coins.cpp:195
void ReallocateCache()
Force a reallocation of the cache map.
Definition: coins.cpp:354
Cursor for iterating over CoinsView state.
Definition: coins.h:222
std::vector< std::function< void()> > m_err_callbacks
A list of callbacks to execute upon leveldb read error.
Definition: coins.h:535
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
Definition: coins.cpp:421
Abstract view on the open txout dataset.
Definition: coins.h:305
virtual bool GetCoin(const COutPoint &outpoint, Coin &coin) const
Retrieve the Coin (unspent transaction output) for a given outpoint.
Definition: coins.cpp:12
virtual CCoinsViewCursor * Cursor() const
Get a cursor to iterate over the whole state.
Definition: coins.cpp:25
virtual std::vector< BlockHash > GetHeadBlocks() const
Retrieve the range of blocks that may have been only partially written.
Definition: coins.cpp:18
virtual BlockHash GetBestBlock() const
Retrieve the block hash whose state this CCoinsView currently represents.
Definition: coins.cpp:15
virtual bool HaveCoin(const COutPoint &outpoint) const
Just check whether a given outpoint is unspent.
Definition: coins.cpp:28
virtual size_t EstimateSize() const
Estimate database size (0 if not implemented)
Definition: coins.h:339
virtual bool BatchWrite(CoinsViewCacheCursor &cursor, const BlockHash &hashBlock)
Do a bulk modification (multiple Coin changes + BestBlock change).
Definition: coins.cpp:21
An output of a transaction.
Definition: transaction.h:128
CScript scriptPubKey
Definition: transaction.h:131
Amount nValue
Definition: transaction.h:130
A UTXO entry.
Definition: coins.h:29
uint32_t GetHeight() const
Definition: coins.h:46
bool IsCoinBase() const
Definition: coins.h:47
CTxOut & GetTxOut()
Definition: coins.h:50
bool IsSpent() const
Definition: coins.h:48
bool IsNull() const
Definition: uint256.h:32
static const size_t MAX_OUTPUTS_PER_TX
Definition: coins.cpp:407
const Coin & AccessByTxid(const CCoinsViewCache &view, const TxId &txid)
Utility function to find any unspent output with a given txid.
Definition: coins.cpp:410
static const Coin coinEmpty
Definition: coins.cpp:193
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.
Definition: coins.cpp:155
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...
Definition: coins.h:217
CCoinsMap::allocator_type::ResourceType CCoinsMapMemoryResource
Definition: coins.h:219
static const uint64_t MAX_TX_SIZE
The maximum allowed size for a transaction, in bytes.
Definition: consensus.h:14
#define LogPrintf(...)
Definition: logging.h:424
unsigned int nHeight
static size_t DynamicUsage(const int8_t &v)
Dynamic memory usage for built-in types is zero.
Definition: memusage.h:28
size_t GetSerializeSize(const T &t)
Definition: serialize.h:1262
std::string ToString() const
Definition: amount.cpp:22
A BlockHash is a unqiue identifier for a block.
Definition: blockhash.h:13
A Coin in one level of the coins database caching hierarchy.
Definition: coins.h:95
Coin coin
Definition: coins.h:135
static void SetFresh(CoinsCachePair &pair, CoinsCachePair &sentinel) noexcept
Definition: coins.h:166
static void SetDirty(CoinsCachePair &pair, CoinsCachePair &sentinel) noexcept
Definition: coins.h:162
Cursor for iterating over the linked list of flagged entries in CCoinsViewCache.
Definition: coins.h:255
CoinsCachePair * NextAndMaybeErase(CoinsCachePair &current) noexcept
Return the next entry after current, possibly erasing current.
Definition: coins.h:278
bool WillErase(CoinsCachePair &current) const noexcept
Definition: coins.h:293
CoinsCachePair * Begin() const noexcept
Definition: coins.h:272
CoinsCachePair * End() const noexcept
Definition: coins.h:275
A TxId is the identifier of a transaction.
Definition: txid.h:14
#define TRACE5(context, event, a, b, c, d, e)
Definition: trace.h:44
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:68
assert(!tx.IsCoinBase())