LCOV - code coverage report
Current view: top level - src - coins.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 141 148 95.3 %
Date: 2015-10-12 22:39:14 Functions: 27 35 77.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2012-2014 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 "memusage.h"
       8             : #include "random.h"
       9             : 
      10             : #include <assert.h>
      11             : 
      12             : /**
      13             :  * calculate number of bytes for the bitmask, and its number of non-zero bytes
      14             :  * each bit in the bitmask represents the availability of one output, but the
      15             :  * availabilities of the first two outputs are encoded separately
      16             :  */
      17       11028 : void CCoins::CalcMaskSize(unsigned int &nBytes, unsigned int &nNonzeroBytes) const {
      18       11028 :     unsigned int nLastUsedByte = 0;
      19       22160 :     for (unsigned int b = 0; 2+b*8 < vout.size(); b++) {
      20             :         bool fZero = true;
      21         100 :         for (unsigned int i = 0; i < 8 && 2+b*8+i < vout.size(); i++) {
      22         200 :             if (!vout[2+b*8+i].IsNull()) {
      23         100 :                 fZero = false;
      24         100 :                 continue;
      25             :             }
      26             :         }
      27          52 :         if (!fZero) {
      28          52 :             nLastUsedByte = b + 1;
      29          52 :             nNonzeroBytes++;
      30             :         }
      31             :     }
      32       11028 :     nBytes += nLastUsedByte;
      33       11028 : }
      34             : 
      35        7311 : bool CCoins::Spend(uint32_t nPos) 
      36             : {
      37       21933 :     if (nPos >= vout.size() || vout[nPos].IsNull())
      38             :         return false;
      39       14622 :     vout[nPos].SetNull();
      40        7311 :     Cleanup();
      41        7311 :     return true;
      42             : }
      43             : 
      44          16 : bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return false; }
      45           0 : bool CCoinsView::HaveCoins(const uint256 &txid) const { return false; }
      46           0 : uint256 CCoinsView::GetBestBlock() const { return uint256(); }
      47           0 : bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return false; }
      48           0 : bool CCoinsView::GetStats(CCoinsStats &stats) const { return false; }
      49             : 
      50             : 
      51       41222 : CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { }
      52       19258 : bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) const { return base->GetCoins(txid, coins); }
      53           0 : bool CCoinsViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); }
      54         662 : uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); }
      55        1148 : void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
      56         130 : bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
      57           0 : bool CCoinsViewBacked::GetStats(CCoinsStats &stats) const { return base->GetStats(stats); }
      58             : 
      59       19937 : CCoinsKeyHasher::CCoinsKeyHasher() : salt(GetRandHash()) {}
      60             : 
      61       79748 : CCoinsViewCache::CCoinsViewCache(CCoinsView *baseIn) : CCoinsViewBacked(baseIn), hasModifier(false), cachedCoinsUsage(0) { }
      62             : 
      63       59930 : CCoinsViewCache::~CCoinsViewCache()
      64             : {
      65       19937 :     assert(!hasModifier);
      66       20056 : }
      67             : 
      68       38027 : size_t CCoinsViewCache::DynamicMemoryUsage() const {
      69       76054 :     return memusage::DynamicUsage(cacheCoins) + cachedCoinsUsage;
      70             : }
      71             : 
      72      513355 : CCoinsMap::const_iterator CCoinsViewCache::FetchCoins(const uint256 &txid) const {
      73     1026710 :     CCoinsMap::iterator it = cacheCoins.find(txid);
      74      513355 :     if (it != cacheCoins.end())
      75      200365 :         return it;
      76      312990 :     CCoins tmp;
      77      312990 :     if (!base->GetCoins(txid, tmp))
      78      122341 :         return cacheCoins.end();
      79      953245 :     CCoinsMap::iterator ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry())).first;
      80      190649 :     tmp.swap(ret->second.coins);
      81      190649 :     if (ret->second.coins.IsPruned()) {
      82             :         // The parent only has an empty entry for this txid; we can consider our
      83             :         // version as fresh.
      84       50054 :         ret->second.flags = CCoinsCacheEntry::FRESH;
      85             :     }
      86      190649 :     cachedCoinsUsage += ret->second.coins.DynamicMemoryUsage();
      87      190649 :     return ret;
      88             : }
      89             : 
      90      256796 : bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) const {
      91      256796 :     CCoinsMap::const_iterator it = FetchCoins(txid);
      92      513592 :     if (it != cacheCoins.end()) {
      93      177310 :         coins = it->second.coins;
      94      177310 :         return true;
      95             :     }
      96             :     return false;
      97             : }
      98             : 
      99       71383 : CCoinsModifier CCoinsViewCache::ModifyCoins(const uint256 &txid) {
     100       71383 :     assert(!hasModifier);
     101      356915 :     std::pair<CCoinsMap::iterator, bool> ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry()));
     102       71383 :     size_t cachedCoinUsage = 0;
     103       71383 :     if (ret.second) {
     104      108820 :         if (!base->GetCoins(txid, ret.first->second.coins)) {
     105             :             // The parent view does not have this entry; mark it as fresh.
     106       23670 :             ret.first->second.coins.Clear();
     107       23670 :             ret.first->second.flags = CCoinsCacheEntry::FRESH;
     108       30740 :         } else if (ret.first->second.coins.IsPruned()) {
     109             :             // The parent view only has a pruned entry for this; mark it as fresh.
     110        5112 :             ret.first->second.flags = CCoinsCacheEntry::FRESH;
     111             :         }
     112             :     } else {
     113       16973 :         cachedCoinUsage = ret.first->second.coins.DynamicMemoryUsage();
     114             :     }
     115             :     // Assume that whenever ModifyCoins is called, the entry will be modified.
     116       71383 :     ret.first->second.flags |= CCoinsCacheEntry::DIRTY;
     117       71383 :     return CCoinsModifier(*this, ret.first, cachedCoinUsage);
     118             : }
     119             : 
     120      227198 : const CCoins* CCoinsViewCache::AccessCoins(const uint256 &txid) const {
     121      252322 :     CCoinsMap::const_iterator it = FetchCoins(txid);
     122      504644 :     if (it == cacheCoins.end()) {
     123             :         return NULL;
     124             :     } else {
     125      212375 :         return &it->second.coins;
     126             :     }
     127             : }
     128             : 
     129        4237 : bool CCoinsViewCache::HaveCoins(const uint256 &txid) const {
     130        4237 :     CCoinsMap::const_iterator it = FetchCoins(txid);
     131             :     // We're using vtx.empty() instead of IsPruned here for performance reasons,
     132             :     // as we only care about the case where a transaction was replaced entirely
     133             :     // in a reorganization (which wipes vout entirely, as opposed to spending
     134             :     // which just cleans individual outputs).
     135       11132 :     return (it != cacheCoins.end() && !it->second.coins.vout.empty());
     136             : }
     137             : 
     138       33183 : uint256 CCoinsViewCache::GetBestBlock() const {
     139       66366 :     if (hashBlock.IsNull())
     140        8246 :         hashBlock = base->GetBestBlock();
     141       33183 :     return hashBlock;
     142             : }
     143             : 
     144       16636 : void CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) {
     145       16636 :     hashBlock = hashBlockIn;
     146       16636 : }
     147             : 
     148        5694 : bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn) {
     149        5694 :     assert(!hasModifier);
     150      193376 :     for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
     151      181988 :         if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization).
     152      107870 :             CCoinsMap::iterator itUs = cacheCoins.find(it->first);
     153       53935 :             if (itUs == cacheCoins.end()) {
     154       18108 :                 if (!it->second.coins.IsPruned()) {
     155             :                     // The parent cache does not have an entry, while the child
     156             :                     // cache does have (a non-pruned) one. Move the data up, and
     157             :                     // mark it as fresh (if the grandparent did have it, we
     158             :                     // would have pulled it in at first GetCoins).
     159       18108 :                     assert(it->second.flags & CCoinsCacheEntry::FRESH);
     160       36216 :                     CCoinsCacheEntry& entry = cacheCoins[it->first];
     161       18108 :                     entry.coins.swap(it->second.coins);
     162       18108 :                     cachedCoinsUsage += entry.coins.DynamicMemoryUsage();
     163       18108 :                     entry.flags = CCoinsCacheEntry::DIRTY | CCoinsCacheEntry::FRESH;
     164             :                 }
     165             :             } else {
     166       46248 :                 if ((itUs->second.flags & CCoinsCacheEntry::FRESH) && it->second.coins.IsPruned()) {
     167             :                     // The grandparent does not have an entry, and the child is
     168             :                     // modified and being pruned. This means we can just delete
     169             :                     // it from the parent.
     170        2792 :                     cachedCoinsUsage -= itUs->second.coins.DynamicMemoryUsage();
     171        2792 :                     cacheCoins.erase(itUs);
     172             :                 } else {
     173             :                     // A normal modification.
     174       33035 :                     cachedCoinsUsage -= itUs->second.coins.DynamicMemoryUsage();
     175       66070 :                     itUs->second.coins.swap(it->second.coins);
     176       33035 :                     cachedCoinsUsage += itUs->second.coins.DynamicMemoryUsage();
     177       33035 :                     itUs->second.flags |= CCoinsCacheEntry::DIRTY;
     178             :                 }
     179             :             }
     180             :         }
     181      363976 :         CCoinsMap::iterator itOld = it++;
     182             :         mapCoins.erase(itOld);
     183             :     }
     184        5694 :     hashBlock = hashBlockIn;
     185        5694 :     return true;
     186             : }
     187             : 
     188        5892 : bool CCoinsViewCache::Flush() {
     189        5892 :     bool fOk = base->BatchWrite(cacheCoins, hashBlock);
     190        5892 :     cacheCoins.clear();
     191        5892 :     cachedCoinsUsage = 0;
     192        5892 :     return fOk;
     193             : }
     194             : 
     195        5709 : unsigned int CCoinsViewCache::GetCacheSize() const {
     196        5709 :     return cacheCoins.size();
     197             : }
     198             : 
     199        9736 : const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input) const
     200             : {
     201       19472 :     const CCoins* coins = AccessCoins(input.prevout.hash);
     202       19472 :     assert(coins && coins->IsAvailable(input.prevout.n));
     203       19472 :     return coins->vout[input.prevout.n];
     204             : }
     205             : 
     206        3635 : CAmount CCoinsViewCache::GetValueIn(const CTransaction& tx) const
     207             : {
     208        3635 :     if (tx.IsCoinBase())
     209             :         return 0;
     210             : 
     211             :     CAmount nResult = 0;
     212       13349 :     for (unsigned int i = 0; i < tx.vin.size(); i++)
     213        9714 :         nResult += GetOutputFor(tx.vin[i]).nValue;
     214             : 
     215        3635 :     return nResult;
     216             : }
     217             : 
     218       10334 : bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const
     219             : {
     220       10334 :     if (!tx.IsCoinBase()) {
     221       38992 :         for (unsigned int i = 0; i < tx.vin.size(); i++) {
     222       28714 :             const COutPoint &prevout = tx.vin[i].prevout;
     223       28714 :             const CCoins* coins = AccessCoins(prevout.hash);
     224       28691 :             if (!coins || !coins->IsAvailable(prevout.n)) {
     225             :                 return false;
     226             :             }
     227             :         }
     228             :     }
     229             :     return true;
     230             : }
     231             : 
     232         557 : double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight) const
     233             : {
     234         557 :     if (tx.IsCoinBase())
     235             :         return 0.0;
     236         557 :     double dResult = 0.0;
     237        8971 :     BOOST_FOREACH(const CTxIn& txin, tx.vin)
     238             :     {
     239        2062 :         const CCoins* coins = AccessCoins(txin.prevout.hash);
     240        1031 :         assert(coins);
     241        2062 :         if (!coins->IsAvailable(txin.prevout.n)) continue;
     242        1031 :         if (coins->nHeight < nHeight) {
     243        1408 :             dResult += coins->vout[txin.prevout.n].nValue * (nHeight-coins->nHeight);
     244             :         }
     245             :     }
     246         557 :     return tx.ComputePriority(dResult);
     247             : }
     248             : 
     249       71383 : CCoinsModifier::CCoinsModifier(CCoinsViewCache& cache_, CCoinsMap::iterator it_, size_t usage) : cache(cache_), it(it_), cachedCoinUsage(usage) {
     250       71383 :     assert(!cache.hasModifier);
     251       71383 :     cache.hasModifier = true;
     252           0 : }
     253             : 
     254       71383 : CCoinsModifier::~CCoinsModifier()
     255             : {
     256       71383 :     assert(cache.hasModifier);
     257       71383 :     cache.hasModifier = false;
     258      142766 :     it->second.coins.Cleanup();
     259       71383 :     cache.cachedCoinsUsage -= cachedCoinUsage; // Subtract the old usage
     260      177448 :     if ((it->second.flags & CCoinsCacheEntry::FRESH) && it->second.coins.IsPruned()) {
     261        7128 :         cache.cacheCoins.erase(it);
     262             :     } else {
     263             :         // If the coin still exists after the modification, add the new usage
     264      135638 :         cache.cachedCoinsUsage += it->second.coins.DynamicMemoryUsage();
     265             :     }
     266       71383 : }

Generated by: LCOV version 1.11