LCOV - code coverage report
Current view: top level - src - coins.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 158 179 88.3 %
Date: 2020-09-26 01:30:44 Functions: 32 42 76.2 %

          Line data    Source code
       1             : // Copyright (c) 2012-2019 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             : 
       7             : #include <consensus/consensus.h>
       8             : #include <logging.h>
       9             : #include <random.h>
      10             : #include <version.h>
      11             : 
      12           5 : bool CCoinsView::GetCoin(const COutPoint &outpoint, Coin &coin) const { return false; }
      13           0 : uint256 CCoinsView::GetBestBlock() const { return uint256(); }
      14           0 : std::vector<uint256> CCoinsView::GetHeadBlocks() const { return std::vector<uint256>(); }
      15           0 : bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return false; }
      16           0 : CCoinsViewCursor *CCoinsView::Cursor() const { return nullptr; }
      17             : 
      18           0 : bool CCoinsView::HaveCoin(const COutPoint &outpoint) const
      19             : {
      20           0 :     Coin coin;
      21           0 :     return GetCoin(outpoint, coin);
      22           0 : }
      23             : 
      24      458314 : CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { }
      25      769695 : bool CCoinsViewBacked::GetCoin(const COutPoint &outpoint, Coin &coin) const { return base->GetCoin(outpoint, coin); }
      26           0 : bool CCoinsViewBacked::HaveCoin(const COutPoint &outpoint) const { return base->HaveCoin(outpoint); }
      27       20343 : uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); }
      28           0 : std::vector<uint256> CCoinsViewBacked::GetHeadBlocks() const { return base->GetHeadBlocks(); }
      29       42334 : void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
      30        1350 : bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
      31           0 : CCoinsViewCursor *CCoinsViewBacked::Cursor() const { return base->Cursor(); }
      32           0 : size_t CCoinsViewBacked::EstimateSize() const { return base->EstimateSize(); }
      33             : 
      34      816938 : SaltedOutpointHasher::SaltedOutpointHasher() : k0(GetRand(std::numeric_limits<uint64_t>::max())), k1(GetRand(std::numeric_limits<uint64_t>::max())) {}
      35             : 
      36      815350 : CCoinsViewCache::CCoinsViewCache(CCoinsView *baseIn) : CCoinsViewBacked(baseIn), cachedCoinsUsage(0) {}
      37             : 
      38      376708 : size_t CCoinsViewCache::DynamicMemoryUsage() const {
      39      376708 :     return memusage::DynamicUsage(cacheCoins) + cachedCoinsUsage;
      40             : }
      41             : 
      42    66989887 : CCoinsMap::iterator CCoinsViewCache::FetchCoin(const COutPoint &outpoint) const {
      43    66989887 :     CCoinsMap::iterator it = cacheCoins.find(outpoint);
      44    66989887 :     if (it != cacheCoins.end())
      45    29132220 :         return it;
      46    37857667 :     Coin tmp;
      47    37857667 :     if (!base->GetCoin(outpoint, tmp))
      48    30047616 :         return cacheCoins.end();
      49     7810051 :     CCoinsMap::iterator ret = cacheCoins.emplace(std::piecewise_construct, std::forward_as_tuple(outpoint), std::forward_as_tuple(std::move(tmp))).first;
      50     7810051 :     if (ret->second.coin.IsSpent()) {
      51             :         // The parent only has an empty entry for this outpoint; we can consider our
      52             :         // version as fresh.
      53      164687 :         ret->second.flags = CCoinsCacheEntry::FRESH;
      54      164687 :     }
      55     7810051 :     cachedCoinsUsage += ret->second.coin.DynamicMemoryUsage();
      56     7810051 :     return ret;
      57    66989887 : }
      58             : 
      59    25661195 : bool CCoinsViewCache::GetCoin(const COutPoint &outpoint, Coin &coin) const {
      60    25661195 :     CCoinsMap::const_iterator it = FetchCoin(outpoint);
      61    25661195 :     if (it != cacheCoins.end()) {
      62     7805563 :         coin = it->second.coin;
      63     7805563 :         return !coin.IsSpent();
      64             :     }
      65    17855632 :     return false;
      66    25661195 : }
      67             : 
      68    11109722 : void CCoinsViewCache::AddCoin(const COutPoint &outpoint, Coin&& coin, bool possible_overwrite) {
      69    11109722 :     assert(!coin.IsSpent());
      70    11109722 :     if (coin.out.scriptPubKey.IsUnspendable()) return;
      71    10579030 :     CCoinsMap::iterator it;
      72    10579030 :     bool inserted;
      73    10579030 :     std::tie(it, inserted) = cacheCoins.emplace(std::piecewise_construct, std::forward_as_tuple(outpoint), std::tuple<>());
      74             :     bool fresh = false;
      75    10579030 :     if (!inserted) {
      76       12464 :         cachedCoinsUsage -= it->second.coin.DynamicMemoryUsage();
      77       12464 :     }
      78    10579030 :     if (!possible_overwrite) {
      79    10460783 :         if (!it->second.coin.IsSpent()) {
      80          12 :             throw std::logic_error("Attempted to overwrite an unspent coin (when possible_overwrite is false)");
      81             :         }
      82             :         // If the coin exists in this cache as a spent coin and is DIRTY, then
      83             :         // its spentness hasn't been flushed to the parent cache. We're
      84             :         // re-adding the coin to this cache now but we can't mark it as FRESH.
      85             :         // If we mark it FRESH and then spend it before the cache is flushed
      86             :         // we would remove it from this cache and would never flush spentness
      87             :         // to the parent cache.
      88             :         //
      89             :         // Re-adding a spent coin can happen in the case of a re-org (the coin
      90             :         // is 'spent' when the block adding it is disconnected and then
      91             :         // re-added when it is also added in a newly connected block).
      92             :         //
      93             :         // If the coin doesn't exist in the current cache, or is spent but not
      94             :         // DIRTY, then it can be marked FRESH.
      95    10460771 :         fresh = !(it->second.flags & CCoinsCacheEntry::DIRTY);
      96    10460771 :     }
      97    10579018 :     it->second.coin = std::move(coin);
      98    10579018 :     it->second.flags |= CCoinsCacheEntry::DIRTY | (fresh ? CCoinsCacheEntry::FRESH : 0);
      99    10579018 :     cachedCoinsUsage += it->second.coin.DynamicMemoryUsage();
     100    11109710 : }
     101             : 
     102     5277746 : void AddCoins(CCoinsViewCache& cache, const CTransaction &tx, int nHeight, bool check_for_overwrite) {
     103     5277746 :     bool fCoinbase = tx.IsCoinBase();
     104     5277746 :     const uint256& txid = tx.GetHash();
     105    16319103 :     for (size_t i = 0; i < tx.vout.size(); ++i) {
     106    11041357 :         bool overwrite = check_for_overwrite ? cache.HaveCoin(COutPoint(txid, i)) : fCoinbase;
     107             :         // Coinbase transactions can always be overwritten, in order to correctly
     108             :         // deal with the pre-BIP30 occurrences of duplicate coinbase transactions.
     109    11041357 :         cache.AddCoin(COutPoint(txid, i), Coin(tx.vout[i], nHeight, fCoinbase), overwrite);
     110             :     }
     111     5277746 : }
     112             : 
     113     6921267 : bool CCoinsViewCache::SpendCoin(const COutPoint &outpoint, Coin* moveout) {
     114     6921267 :     CCoinsMap::iterator it = FetchCoin(outpoint);
     115     6921267 :     if (it == cacheCoins.end()) return false;
     116     6921265 :     cachedCoinsUsage -= it->second.coin.DynamicMemoryUsage();
     117     6921265 :     if (moveout) {
     118     6887360 :         *moveout = std::move(it->second.coin);
     119     6887360 :     }
     120     6921265 :     if (it->second.flags & CCoinsCacheEntry::FRESH) {
     121       51383 :         cacheCoins.erase(it);
     122       51383 :     } else {
     123     6869882 :         it->second.flags |= CCoinsCacheEntry::DIRTY;
     124     6869882 :         it->second.coin.Clear();
     125             :     }
     126     6921265 :     return true;
     127     6921267 : }
     128             : 
     129         731 : static const Coin coinEmpty;
     130             : 
     131    19211053 : const Coin& CCoinsViewCache::AccessCoin(const COutPoint &outpoint) const {
     132    19211053 :     CCoinsMap::const_iterator it = FetchCoin(outpoint);
     133    19211053 :     if (it == cacheCoins.end()) {
     134    11053843 :         return coinEmpty;
     135             :     } else {
     136     8157210 :         return it->second.coin;
     137             :     }
     138    19211053 : }
     139             : 
     140    15196372 : bool CCoinsViewCache::HaveCoin(const COutPoint &outpoint) const {
     141    15196372 :     CCoinsMap::const_iterator it = FetchCoin(outpoint);
     142    15196372 :     return (it != cacheCoins.end() && !it->second.coin.IsSpent());
     143    15196372 : }
     144             : 
     145      290703 : bool CCoinsViewCache::HaveCoinInCache(const COutPoint &outpoint) const {
     146      290703 :     CCoinsMap::const_iterator it = cacheCoins.find(outpoint);
     147      290703 :     return (it != cacheCoins.end() && !it->second.coin.IsSpent());
     148      290703 : }
     149             : 
     150      316404 : uint256 CCoinsViewCache::GetBestBlock() const {
     151      316404 :     if (hashBlock.IsNull())
     152      145008 :         hashBlock = base->GetBestBlock();
     153      316404 :     return hashBlock;
     154             : }
     155             : 
     156      471900 : void CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) {
     157      471900 :     hashBlock = hashBlockIn;
     158      471900 : }
     159             : 
     160       50795 : bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn) {
     161      778800 :     for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end(); it = mapCoins.erase(it)) {
     162             :         // Ignore non-dirty entries (optimization).
     163      728013 :         if (!(it->second.flags & CCoinsCacheEntry::DIRTY)) {
     164             :             continue;
     165             :         }
     166      445624 :         CCoinsMap::iterator itUs = cacheCoins.find(it->first);
     167      445624 :         if (itUs == cacheCoins.end()) {
     168             :             // The parent cache does not have an entry, while the child cache does.
     169             :             // We can ignore it if it's both spent and FRESH in the child
     170      340316 :             if (!(it->second.flags & CCoinsCacheEntry::FRESH && it->second.coin.IsSpent())) {
     171             :                 // Create the coin in the parent cache, move the data up
     172             :                 // and mark it as dirty.
     173      340315 :                 CCoinsCacheEntry& entry = cacheCoins[it->first];
     174      340315 :                 entry.coin = std::move(it->second.coin);
     175      340315 :                 cachedCoinsUsage += entry.coin.DynamicMemoryUsage();
     176      340315 :                 entry.flags = CCoinsCacheEntry::DIRTY;
     177             :                 // We can mark it FRESH in the parent if it was FRESH in the child
     178             :                 // Otherwise it might have just been flushed from the parent's cache
     179             :                 // and already exist in the grandparent
     180      340315 :                 if (it->second.flags & CCoinsCacheEntry::FRESH) {
     181      177322 :                     entry.flags |= CCoinsCacheEntry::FRESH;
     182      177322 :                 }
     183      340315 :             }
     184             :         } else {
     185             :             // Found the entry in the parent cache
     186      105308 :             if ((it->second.flags & CCoinsCacheEntry::FRESH) && !itUs->second.coin.IsSpent()) {
     187             :                 // The coin was marked FRESH in the child cache, but the coin
     188             :                 // exists in the parent cache. If this ever happens, it means
     189             :                 // the FRESH flag was misapplied and there is a logic error in
     190             :                 // the calling code.
     191           8 :                 throw std::logic_error("FRESH flag misapplied to coin that exists in parent cache");
     192             :             }
     193             : 
     194      105300 :             if ((itUs->second.flags & CCoinsCacheEntry::FRESH) && it->second.coin.IsSpent()) {
     195             :                 // The grandparent cache does not have an entry, and the coin
     196             :                 // has been spent. We can just delete it from the parent cache.
     197       53575 :                 cachedCoinsUsage -= itUs->second.coin.DynamicMemoryUsage();
     198       53575 :                 cacheCoins.erase(itUs);
     199       53575 :             } else {
     200             :                 // A normal modification.
     201       51725 :                 cachedCoinsUsage -= itUs->second.coin.DynamicMemoryUsage();
     202       51725 :                 itUs->second.coin = std::move(it->second.coin);
     203       51725 :                 cachedCoinsUsage += itUs->second.coin.DynamicMemoryUsage();
     204       51725 :                 itUs->second.flags |= CCoinsCacheEntry::DIRTY;
     205             :                 // NOTE: It isn't safe to mark the coin as FRESH in the parent
     206             :                 // cache. If it already existed and was spent in the parent
     207             :                 // cache then marking it FRESH would prevent that spentness
     208             :                 // from being flushed to the grandparent.
     209             :             }
     210             :         }
     211      445616 :     }
     212       50787 :     hashBlock = hashBlockIn;
     213       50787 :     return true;
     214           0 : }
     215             : 
     216       52273 : bool CCoinsViewCache::Flush() {
     217       52273 :     bool fOk = base->BatchWrite(cacheCoins, hashBlock);
     218       52273 :     cacheCoins.clear();
     219       52273 :     cachedCoinsUsage = 0;
     220       52273 :     return fOk;
     221             : }
     222             : 
     223       15689 : void CCoinsViewCache::Uncache(const COutPoint& hash)
     224             : {
     225       15689 :     CCoinsMap::iterator it = cacheCoins.find(hash);
     226       15689 :     if (it != cacheCoins.end() && it->second.flags == 0) {
     227        1080 :         cachedCoinsUsage -= it->second.coin.DynamicMemoryUsage();
     228        1080 :         cacheCoins.erase(it);
     229        1080 :     }
     230       15689 : }
     231             : 
     232      213081 : unsigned int CCoinsViewCache::GetCacheSize() const {
     233      213081 :     return cacheCoins.size();
     234             : }
     235             : 
     236     5193226 : bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const
     237             : {
     238     5193226 :     if (!tx.IsCoinBase()) {
     239    12066347 :         for (unsigned int i = 0; i < tx.vin.size(); i++) {
     240     6873208 :             if (!HaveCoin(tx.vin[i].prevout)) {
     241          87 :                 return false;
     242             :             }
     243             :         }
     244             :     }
     245     5193139 :     return true;
     246     5193226 : }
     247             : 
     248           4 : void CCoinsViewCache::ReallocateCache()
     249             : {
     250             :     // Cache should be empty when we're calling this.
     251           4 :     assert(cacheCoins.size() == 0);
     252           4 :     cacheCoins.~CCoinsMap();
     253           4 :     ::new (&cacheCoins) CCoinsMap();
     254           4 : }
     255             : 
     256         731 : static const size_t MIN_TRANSACTION_OUTPUT_WEIGHT = WITNESS_SCALE_FACTOR * ::GetSerializeSize(CTxOut(), PROTOCOL_VERSION);
     257         731 : static const size_t MAX_OUTPUTS_PER_BLOCK = MAX_BLOCK_WEIGHT / MIN_TRANSACTION_OUTPUT_WEIGHT;
     258             : 
     259         198 : const Coin& AccessByTxid(const CCoinsViewCache& view, const uint256& txid)
     260             : {
     261         198 :     COutPoint iter(txid, 0);
     262    10222410 :     while (iter.n < MAX_OUTPUTS_PER_BLOCK) {
     263    10222318 :         const Coin& alternate = view.AccessCoin(iter);
     264    10222318 :         if (!alternate.IsSpent()) return alternate;
     265    10222212 :         ++iter.n;
     266    10222212 :     }
     267          92 :     return coinEmpty;
     268         198 : }
     269             : 
     270      769695 : bool CCoinsViewErrorCatcher::GetCoin(const COutPoint &outpoint, Coin &coin) const {
     271             :     try {
     272      769695 :         return CCoinsViewBacked::GetCoin(outpoint, coin);
     273           0 :     } catch(const std::runtime_error& e) {
     274           0 :         for (auto f : m_err_callbacks) {
     275           0 :             f();
     276           0 :         }
     277           0 :         LogPrintf("Error reading from database: %s\n", e.what());
     278             :         // Starting the shutdown sequence and returning false to the caller would be
     279             :         // interpreted as 'entry not found' (as opposed to unable to read data), and
     280             :         // could lead to invalid interpretation. Just exit immediately, as we can't
     281             :         // continue anyway, and all writes should be atomic.
     282           0 :         std::abort();
     283           0 :     }
     284           0 : }

Generated by: LCOV version 1.15