Bitcoin Core  21.99.0
P2P Digital Currency
coinstats.cpp
Go to the documentation of this file.
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 <crypto/muhash.h>
10 #include <hash.h>
11 #include <serialize.h>
12 #include <uint256.h>
13 #include <util/system.h>
14 #include <validation.h>
15 
16 #include <map>
17 
18 // Database-independent metric indicating the UTXO set size
19 static uint64_t GetBogoSize(const CScript& scriptPubKey)
20 {
21  return 32 /* txid */ +
22  4 /* vout index */ +
23  4 /* height + coinbase */ +
24  8 /* amount */ +
25  2 /* scriptPubKey len */ +
26  scriptPubKey.size() /* scriptPubKey */;
27 }
28 
29 static void ApplyHash(CCoinsStats& stats, CHashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs, std::map<uint32_t, Coin>::const_iterator it)
30 {
31  if (it == outputs.begin()) {
32  ss << hash;
33  ss << VARINT(it->second.nHeight * 2 + it->second.fCoinBase ? 1u : 0u);
34  }
35 
36  ss << VARINT(it->first + 1);
37  ss << it->second.out.scriptPubKey;
38  ss << VARINT_MODE(it->second.out.nValue, VarIntMode::NONNEGATIVE_SIGNED);
39 
40  if (it == std::prev(outputs.end())) {
41  ss << VARINT(0u);
42  }
43 }
44 
45 static void ApplyHash(CCoinsStats& stats, std::nullptr_t, const uint256& hash, const std::map<uint32_t, Coin>& outputs, std::map<uint32_t, Coin>::const_iterator it) {}
46 
47 static void ApplyHash(CCoinsStats& stats, MuHash3072& muhash, const uint256& hash, const std::map<uint32_t, Coin>& outputs, std::map<uint32_t, Coin>::const_iterator it)
48 {
49  COutPoint outpoint = COutPoint(hash, it->first);
50  Coin coin = it->second;
51 
53  ss << outpoint;
54  ss << static_cast<uint32_t>(coin.nHeight * 2 + coin.fCoinBase);
55  ss << coin.out;
56  muhash.Insert(MakeUCharSpan(ss));
57 }
58 
71 template <typename T>
72 static void ApplyStats(CCoinsStats& stats, T& hash_obj, const uint256& hash, const std::map<uint32_t, Coin>& outputs)
73 {
74  assert(!outputs.empty());
75  stats.nTransactions++;
76  for (auto it = outputs.begin(); it != outputs.end(); ++it) {
77  ApplyHash(stats, hash_obj, hash, outputs, it);
78 
79  stats.nTransactionOutputs++;
80  stats.nTotalAmount += it->second.out.nValue;
81  stats.nBogoSize += GetBogoSize(it->second.out.scriptPubKey);
82  }
83 }
84 
86 template <typename T>
87 static bool GetUTXOStats(CCoinsView* view, BlockManager& blockman, CCoinsStats& stats, T hash_obj, const std::function<void()>& interruption_point)
88 {
89  stats = CCoinsStats();
90  std::unique_ptr<CCoinsViewCursor> pcursor(view->Cursor());
91  assert(pcursor);
92 
93  stats.hashBlock = pcursor->GetBestBlock();
94  {
95  LOCK(cs_main);
96  assert(std::addressof(g_chainman.m_blockman) == std::addressof(blockman));
97  const CBlockIndex* block = blockman.LookupBlockIndex(stats.hashBlock);
98  stats.nHeight = Assert(block)->nHeight;
99  }
100 
101  PrepareHash(hash_obj, stats);
102 
103  uint256 prevkey;
104  std::map<uint32_t, Coin> outputs;
105  while (pcursor->Valid()) {
106  interruption_point();
107  COutPoint key;
108  Coin coin;
109  if (pcursor->GetKey(key) && pcursor->GetValue(coin)) {
110  if (!outputs.empty() && key.hash != prevkey) {
111  ApplyStats(stats, hash_obj, prevkey, outputs);
112  outputs.clear();
113  }
114  prevkey = key.hash;
115  outputs[key.n] = std::move(coin);
116  stats.coins_count++;
117  } else {
118  return error("%s: unable to read value", __func__);
119  }
120  pcursor->Next();
121  }
122  if (!outputs.empty()) {
123  ApplyStats(stats, hash_obj, prevkey, outputs);
124  }
125 
126  FinalizeHash(hash_obj, stats);
127 
128  stats.nDiskSize = view->EstimateSize();
129  return true;
130 }
131 
132 bool GetUTXOStats(CCoinsView* view, BlockManager& blockman, CCoinsStats& stats, CoinStatsHashType hash_type, const std::function<void()>& interruption_point)
133 {
134  switch (hash_type) {
137  return GetUTXOStats(view, blockman, stats, ss, interruption_point);
138  }
140  MuHash3072 muhash;
141  return GetUTXOStats(view, blockman, stats, muhash, interruption_point);
142  }
143  case(CoinStatsHashType::NONE): {
144  return GetUTXOStats(view, blockman, stats, nullptr, interruption_point);
145  }
146  } // no default case, so the compiler can warn about missing cases
147  assert(false);
148 }
149 
150 // The legacy hash serializes the hashBlock
151 static void PrepareHash(CHashWriter& ss, const CCoinsStats& stats)
152 {
153  ss << stats.hashBlock;
154 }
155 // MuHash does not need the prepare step
156 static void PrepareHash(MuHash3072& muhash, CCoinsStats& stats) {}
157 static void PrepareHash(std::nullptr_t, CCoinsStats& stats) {}
158 
159 static void FinalizeHash(CHashWriter& ss, CCoinsStats& stats)
160 {
161  stats.hashSerialized = ss.GetHash();
162 }
163 static void FinalizeHash(MuHash3072& muhash, CCoinsStats& stats)
164 {
165  uint256 out;
166  muhash.Finalize(out);
167  stats.hashSerialized = out;
168 }
169 static void FinalizeHash(std::nullptr_t, CCoinsStats& stats) {}
CoinStatsHashType::HASH_SERIALIZED
@ HASH_SERIALIZED
SER_DISK
@ SER_DISK
Definition: serialize.h:167
MakeUCharSpan
constexpr auto MakeUCharSpan(V &&v) -> decltype(UCharSpanCast(MakeSpan(std::forward< V >(v))))
Like MakeSpan, but for (const) unsigned char member types only.
Definition: span.h:249
COutPoint::hash
uint256 hash
Definition: transaction.h:29
CCoinsStats::nDiskSize
uint64_t nDiskSize
Definition: coinstats.h:32
VARINT_MODE
#define VARINT_MODE(obj, mode)
Definition: serialize.h:478
uint256.h
CCoinsStats::nTransactions
uint64_t nTransactions
Definition: coinstats.h:28
MuHash3072::Insert
MuHash3072 & Insert(Span< const unsigned char > in) noexcept
Definition: muhash.cpp:338
CCoinsStats
Definition: coinstats.h:24
PrepareHash
static void PrepareHash(CHashWriter &ss, const CCoinsStats &stats)
Definition: coinstats.cpp:151
VarIntMode::NONNEGATIVE_SIGNED
@ NONNEGATIVE_SIGNED
Coin::fCoinBase
unsigned int fCoinBase
whether containing transaction was a coinbase
Definition: coins.h:39
BlockManager
Maintains a tree of blocks (stored in m_block_index) which is consulted to determine where the most-w...
Definition: validation.h:364
cs_main
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition: validation.cpp:131
CoinStatsHashType::NONE
@ NONE
Assert
#define Assert(val)
Identity function.
Definition: check.h:57
CCoinsView
Abstract view on the open txout dataset.
Definition: coins.h:159
Coin::out
CTxOut out
unspent transaction output
Definition: coins.h:36
muhash.h
Coin
A UTXO entry.
Definition: coins.h:32
CCoinsStats::hashBlock
uint256 hashBlock
Definition: coinstats.h:27
VARINT
#define VARINT(obj)
Definition: serialize.h:479
Coin::nHeight
uint32_t nHeight
at which height this containing transaction was included in the active block chain
Definition: coins.h:42
g_chainman
ChainstateManager g_chainman
Definition: validation.cpp:106
CoinStatsHashType::MUHASH
@ MUHASH
uint256
256-bit opaque blob.
Definition: uint256.h:124
MuHash3072::Finalize
void Finalize(uint256 &out) noexcept
Definition: muhash.cpp:313
CCoinsView::Cursor
virtual CCoinsViewCursor * Cursor() const
Get a cursor to iterate over the whole state.
Definition: coins.cpp:16
CScript
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:404
CCoinsStats::coins_count
uint64_t coins_count
The number of coins contained.
Definition: coinstats.h:36
CCoinsView::EstimateSize
virtual size_t EstimateSize() const
Estimate database size (0 if not implemented)
Definition: coins.h:191
coins.h
coinstats.h
system.h
BlockManager::LookupBlockIndex
CBlockIndex * LookupBlockIndex(const uint256 &hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Definition: validation.cpp:173
CCoinsStats::nHeight
int nHeight
Definition: coinstats.h:26
GetBogoSize
static uint64_t GetBogoSize(const CScript &scriptPubKey)
Definition: coinstats.cpp:19
CCoinsStats::nTransactionOutputs
uint64_t nTransactionOutputs
Definition: coinstats.h:29
COutPoint::n
uint32_t n
Definition: transaction.h:30
ApplyStats
static void ApplyStats(CCoinsStats &stats, T &hash_obj, const uint256 &hash, const std::map< uint32_t, Coin > &outputs)
Warning: be very careful when changing this! assumeutxo and UTXO snapshot validation commitments are ...
Definition: coinstats.cpp:72
LOCK
#define LOCK(cs)
Definition: sync.h:232
ApplyHash
static void ApplyHash(CCoinsStats &stats, CHashWriter &ss, const uint256 &hash, const std::map< uint32_t, Coin > &outputs, std::map< uint32_t, Coin >::const_iterator it)
Definition: coinstats.cpp:29
CCoinsStats::nBogoSize
uint64_t nBogoSize
Definition: coinstats.h:30
CHashWriter
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:100
CCoinsStats::nTotalAmount
CAmount nTotalAmount
Definition: coinstats.h:33
prevector::size
size_type size() const
Definition: prevector.h:282
serialize.h
CDataStream
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:204
CCoinsStats::hashSerialized
uint256 hashSerialized
Definition: coinstats.h:31
COutPoint
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:26
error
bool error(const char *fmt, const Args &... args)
Definition: system.h:50
CHashWriter::GetHash
uint256 GetHash()
Compute the double-SHA256 hash of all data written to this object.
Definition: hash.h:122
FinalizeHash
static void FinalizeHash(CHashWriter &ss, CCoinsStats &stats)
Definition: coinstats.cpp:159
CBlockIndex
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:137
CoinStatsHashType
CoinStatsHashType
Definition: coinstats.h:18
assert
assert(std::addressof(::ChainstateActive().CoinsTip())==std::addressof(coins_cache))
SER_GETHASH
@ SER_GETHASH
Definition: serialize.h:168
GetUTXOStats
static bool GetUTXOStats(CCoinsView *view, BlockManager &blockman, CCoinsStats &stats, T hash_obj, const std::function< void()> &interruption_point)
Calculate statistics about the unspent transaction output set.
Definition: coinstats.cpp:87
MuHash3072
A class representing MuHash sets.
Definition: muhash.h:94
it
auto it
Definition: validation.cpp:399
PROTOCOL_VERSION
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:12