LCOV - code coverage report
Current view: top level - src/node - coinstats.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 72 74 97.3 %
Date: 2020-09-26 01:30:44 Functions: 10 10 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2020 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             : #include <node/coinstats.h>
       7             : 
       8             : #include <coins.h>
       9             : #include <hash.h>
      10             : #include <serialize.h>
      11             : #include <uint256.h>
      12             : #include <util/system.h>
      13             : #include <validation.h>
      14             : 
      15             : #include <map>
      16             : 
      17        1136 : static uint64_t GetBogoSize(const CScript& scriptPubKey)
      18             : {
      19        1136 :     return 32 /* txid */ +
      20             :            4 /* vout index */ +
      21             :            4 /* height + coinbase */ +
      22             :            8 /* amount */ +
      23        1136 :            2 /* scriptPubKey len */ +
      24        1136 :            scriptPubKey.size() /* scriptPubKey */;
      25             : }
      26             : 
      27         826 : static void ApplyStats(CCoinsStats& stats, CHashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs)
      28             : {
      29         826 :     assert(!outputs.empty());
      30         826 :     ss << hash;
      31         826 :     ss << VARINT(outputs.begin()->second.nHeight * 2 + outputs.begin()->second.fCoinBase ? 1u : 0u);
      32         826 :     stats.nTransactions++;
      33        1662 :     for (const auto& output : outputs) {
      34         836 :         ss << VARINT(output.first + 1);
      35         836 :         ss << output.second.out.scriptPubKey;
      36         836 :         ss << VARINT_MODE(output.second.out.nValue, VarIntMode::NONNEGATIVE_SIGNED);
      37         836 :         stats.nTransactionOutputs++;
      38         836 :         stats.nTotalAmount += output.second.out.nValue;
      39         836 :         stats.nBogoSize += GetBogoSize(output.second.out.scriptPubKey);
      40             :     }
      41         826 :     ss << VARINT(0u);
      42         826 : }
      43             : 
      44         300 : static void ApplyStats(CCoinsStats& stats, std::nullptr_t, const uint256& hash, const std::map<uint32_t, Coin>& outputs)
      45             : {
      46         300 :     assert(!outputs.empty());
      47         300 :     stats.nTransactions++;
      48         600 :     for (const auto& output : outputs) {
      49         300 :         stats.nTransactionOutputs++;
      50         300 :         stats.nTotalAmount += output.second.out.nValue;
      51         300 :         stats.nBogoSize += GetBogoSize(output.second.out.scriptPubKey);
      52             :     }
      53         300 : }
      54             : 
      55             : //! Calculate statistics about the unspent transaction output set
      56             : template <typename T>
      57           7 : static bool GetUTXOStats(CCoinsView* view, CCoinsStats& stats, T hash_obj, const std::function<void()>& interruption_point)
      58             : {
      59           7 :     stats = CCoinsStats();
      60           7 :     std::unique_ptr<CCoinsViewCursor> pcursor(view->Cursor());
      61           7 :     assert(pcursor);
      62             : 
      63           7 :     stats.hashBlock = pcursor->GetBestBlock();
      64             :     {
      65           7 :         LOCK(cs_main);
      66           7 :         stats.nHeight = LookupBlockIndex(stats.hashBlock)->nHeight;
      67           7 :     }
      68             : 
      69           7 :     PrepareHash(hash_obj, stats);
      70             : 
      71           7 :     uint256 prevkey;
      72           7 :     std::map<uint32_t, Coin> outputs;
      73        1143 :     while (pcursor->Valid()) {
      74        1136 :         interruption_point();
      75        1136 :         COutPoint key;
      76        1136 :         Coin coin;
      77        1136 :         if (pcursor->GetKey(key) && pcursor->GetValue(coin)) {
      78        1136 :             if (!outputs.empty() && key.hash != prevkey) {
      79        1120 :                 ApplyStats(stats, hash_obj, prevkey, outputs);
      80        1120 :                 outputs.clear();
      81        1120 :             }
      82        1136 :             prevkey = key.hash;
      83        1136 :             outputs[key.n] = std::move(coin);
      84        1136 :             stats.coins_count++;
      85             :         } else {
      86           0 :             return error("%s: unable to read value", __func__);
      87             :         }
      88        1136 :         pcursor->Next();
      89        1136 :     }
      90           7 :     if (!outputs.empty()) {
      91           6 :         ApplyStats(stats, hash_obj, prevkey, outputs);
      92             :     }
      93             : 
      94           7 :     FinalizeHash(hash_obj, stats);
      95             : 
      96           7 :     stats.nDiskSize = view->EstimateSize();
      97           7 :     return true;
      98           7 : }
      99             : 
     100           7 : bool GetUTXOStats(CCoinsView* view, CCoinsStats& stats, CoinStatsHashType hash_type, const std::function<void()>& interruption_point)
     101             : {
     102           7 :     switch (hash_type) {
     103             :     case(CoinStatsHashType::HASH_SERIALIZED): {
     104           5 :         CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
     105           5 :         return GetUTXOStats(view, stats, ss, interruption_point);
     106           5 :     }
     107             :     case(CoinStatsHashType::NONE): {
     108           2 :         return GetUTXOStats(view, stats, nullptr, interruption_point);
     109             :     }
     110             :     } // no default case, so the compiler can warn about missing cases
     111           0 :     assert(false);
     112           7 : }
     113             : 
     114             : // The legacy hash serializes the hashBlock
     115           5 : static void PrepareHash(CHashWriter& ss, CCoinsStats& stats)
     116             : {
     117           5 :     ss << stats.hashBlock;
     118           5 : }
     119           2 : static void PrepareHash(std::nullptr_t, CCoinsStats& stats) {}
     120             : 
     121           5 : static void FinalizeHash(CHashWriter& ss, CCoinsStats& stats)
     122             : {
     123           5 :     stats.hashSerialized = ss.GetHash();
     124           5 : }
     125           2 : static void FinalizeHash(std::nullptr_t, CCoinsStats& stats) {}

Generated by: LCOV version 1.15