Bitcoin Core 22.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>
12#include <serialize.h>
13#include <uint256.h>
14#include <util/system.h>
15#include <validation.h>
16
17#include <map>
18
19// Database-independent metric indicating the UTXO set size
20uint64_t GetBogoSize(const CScript& script_pub_key)
21{
22 return 32 /* txid */ +
23 4 /* vout index */ +
24 4 /* height + coinbase */ +
25 8 /* amount */ +
26 2 /* scriptPubKey len */ +
27 script_pub_key.size() /* scriptPubKey */;
28}
29
30CDataStream TxOutSer(const COutPoint& outpoint, const Coin& coin) {
32 ss << outpoint;
33 ss << static_cast<uint32_t>(coin.nHeight * 2 + coin.fCoinBase);
34 ss << coin.out;
35 return ss;
36}
37
50static void ApplyHash(CHashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs)
51{
52 for (auto it = outputs.begin(); it != outputs.end(); ++it) {
53 if (it == outputs.begin()) {
54 ss << hash;
55 ss << VARINT(it->second.nHeight * 2 + it->second.fCoinBase ? 1u : 0u);
56 }
57
58 ss << VARINT(it->first + 1);
59 ss << it->second.out.scriptPubKey;
60 ss << VARINT_MODE(it->second.out.nValue, VarIntMode::NONNEGATIVE_SIGNED);
61
62 if (it == std::prev(outputs.end())) {
63 ss << VARINT(0u);
64 }
65 }
66}
67
68static void ApplyHash(std::nullptr_t, const uint256& hash, const std::map<uint32_t, Coin>& outputs) {}
69
70static void ApplyHash(MuHash3072& muhash, const uint256& hash, const std::map<uint32_t, Coin>& outputs)
71{
72 for (auto it = outputs.begin(); it != outputs.end(); ++it) {
73 COutPoint outpoint = COutPoint(hash, it->first);
74 Coin coin = it->second;
75 muhash.Insert(MakeUCharSpan(TxOutSer(outpoint, coin)));
76 }
77}
78
79static void ApplyStats(CCoinsStats& stats, const uint256& hash, const std::map<uint32_t, Coin>& outputs)
80{
81 assert(!outputs.empty());
82 stats.nTransactions++;
83 for (auto it = outputs.begin(); it != outputs.end(); ++it) {
84 stats.nTransactionOutputs++;
85 stats.nTotalAmount += it->second.out.nValue;
86 stats.nBogoSize += GetBogoSize(it->second.out.scriptPubKey);
87 }
88}
89
91template <typename T>
92static bool GetUTXOStats(CCoinsView* view, BlockManager& blockman, CCoinsStats& stats, T hash_obj, const std::function<void()>& interruption_point, const CBlockIndex* pindex)
93{
94 std::unique_ptr<CCoinsViewCursor> pcursor(view->Cursor());
95 assert(pcursor);
96
97 if (!pindex) {
98 {
100 pindex = blockman.LookupBlockIndex(view->GetBestBlock());
101 }
102 }
103 stats.nHeight = Assert(pindex)->nHeight;
104 stats.hashBlock = pindex->GetBlockHash();
105
106 // Use CoinStatsIndex if it is requested and available and a hash_type of Muhash or None was requested
108 stats.index_used = true;
109 return g_coin_stats_index->LookUpStats(pindex, stats);
110 }
111
112 PrepareHash(hash_obj, stats);
113
114 uint256 prevkey;
115 std::map<uint32_t, Coin> outputs;
116 while (pcursor->Valid()) {
117 interruption_point();
118 COutPoint key;
119 Coin coin;
120 if (pcursor->GetKey(key) && pcursor->GetValue(coin)) {
121 if (!outputs.empty() && key.hash != prevkey) {
122 ApplyStats(stats, prevkey, outputs);
123 ApplyHash(hash_obj, prevkey, outputs);
124 outputs.clear();
125 }
126 prevkey = key.hash;
127 outputs[key.n] = std::move(coin);
128 stats.coins_count++;
129 } else {
130 return error("%s: unable to read value", __func__);
131 }
132 pcursor->Next();
133 }
134 if (!outputs.empty()) {
135 ApplyStats(stats, prevkey, outputs);
136 ApplyHash(hash_obj, prevkey, outputs);
137 }
138
139 FinalizeHash(hash_obj, stats);
140
141 stats.nDiskSize = view->EstimateSize();
142 return true;
143}
144
145bool GetUTXOStats(CCoinsView* view, BlockManager& blockman, CCoinsStats& stats, const std::function<void()>& interruption_point, const CBlockIndex* pindex)
146{
147 switch (stats.m_hash_type) {
150 return GetUTXOStats(view, blockman, stats, ss, interruption_point, pindex);
151 }
153 MuHash3072 muhash;
154 return GetUTXOStats(view, blockman, stats, muhash, interruption_point, pindex);
155 }
157 return GetUTXOStats(view, blockman, stats, nullptr, interruption_point, pindex);
158 }
159 } // no default case, so the compiler can warn about missing cases
160 assert(false);
161}
162
163// The legacy hash serializes the hashBlock
164static void PrepareHash(CHashWriter& ss, const CCoinsStats& stats)
165{
166 ss << stats.hashBlock;
167}
168// MuHash does not need the prepare step
169static void PrepareHash(MuHash3072& muhash, CCoinsStats& stats) {}
170static void PrepareHash(std::nullptr_t, CCoinsStats& stats) {}
171
172static void FinalizeHash(CHashWriter& ss, CCoinsStats& stats)
173{
174 stats.hashSerialized = ss.GetHash();
175}
176static void FinalizeHash(MuHash3072& muhash, CCoinsStats& stats)
177{
178 uint256 out;
179 muhash.Finalize(out);
180 stats.hashSerialized = out;
181}
182static void FinalizeHash(std::nullptr_t, CCoinsStats& stats) {}
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition: validation.cpp:118
#define Assert(val)
Identity function.
Definition: check.h:57
Maintains a tree of blocks (stored in m_block_index) which is consulted to determine where the most-w...
Definition: validation.h:375
CBlockIndex * LookupBlockIndex(const uint256 &hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Definition: validation.cpp:150
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:146
uint256 GetBlockHash() const
Definition: chain.h:254
Abstract view on the open txout dataset.
Definition: coins.h:158
virtual size_t EstimateSize() const
Estimate database size (0 if not implemented)
Definition: coins.h:189
virtual std::unique_ptr< CCoinsViewCursor > Cursor() const
Get a cursor to iterate over the whole state.
Definition: coins.cpp:16
virtual uint256 GetBestBlock() const
Retrieve the block hash whose state this CCoinsView currently represents.
Definition: coins.cpp:13
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:205
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:101
uint256 GetHash()
Compute the double-SHA256 hash of all data written to this object.
Definition: hash.h:122
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:27
uint32_t n
Definition: transaction.h:30
uint256 hash
Definition: transaction.h:29
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:406
A UTXO entry.
Definition: coins.h:31
CTxOut out
unspent transaction output
Definition: coins.h:34
uint32_t nHeight
at which height this containing transaction was included in the active block chain
Definition: coins.h:40
unsigned int fCoinBase
whether containing transaction was a coinbase
Definition: coins.h:37
A class representing MuHash sets.
Definition: muhash.h:95
void Finalize(uint256 &out) noexcept
Definition: muhash.cpp:313
MuHash3072 & Insert(Span< const unsigned char > in) noexcept
Definition: muhash.cpp:338
size_type size() const
Definition: prevector.h:282
256-bit opaque blob.
Definition: uint256.h:124
CDataStream TxOutSer(const COutPoint &outpoint, const Coin &coin)
Definition: coinstats.cpp:30
uint64_t GetBogoSize(const CScript &script_pub_key)
Definition: coinstats.cpp:20
static void ApplyStats(CCoinsStats &stats, const uint256 &hash, const std::map< uint32_t, Coin > &outputs)
Definition: coinstats.cpp:79
static void PrepareHash(CHashWriter &ss, const CCoinsStats &stats)
Definition: coinstats.cpp:164
static void FinalizeHash(CHashWriter &ss, CCoinsStats &stats)
Definition: coinstats.cpp:172
static bool GetUTXOStats(CCoinsView *view, BlockManager &blockman, CCoinsStats &stats, T hash_obj, const std::function< void()> &interruption_point, const CBlockIndex *pindex)
Calculate statistics about the unspent transaction output set.
Definition: coinstats.cpp:92
static void ApplyHash(CHashWriter &ss, 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:50
std::unique_ptr< CoinStatsIndex > g_coin_stats_index
The global UTXO set hash object.
#define T(expected, seed, data)
#define VARINT(obj)
Definition: serialize.h:443
#define VARINT_MODE(obj, mode)
Definition: serialize.h:442
@ SER_DISK
Definition: serialize.h:139
@ SER_GETHASH
Definition: serialize.h:140
@ NONNEGATIVE_SIGNED
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
uint64_t nTransactionOutputs
Definition: coinstats.h:33
uint64_t nTransactions
Definition: coinstats.h:32
uint256 hashSerialized
Definition: coinstats.h:35
bool index_used
Signals if the coinstatsindex was used to retrieve the statistics.
Definition: coinstats.h:45
bool index_requested
Signals if the coinstatsindex should be used (when available).
Definition: coinstats.h:43
uint64_t nBogoSize
Definition: coinstats.h:34
int nHeight
Definition: coinstats.h:30
uint64_t nDiskSize
Definition: coinstats.h:36
uint64_t coins_count
The number of coins contained.
Definition: coinstats.h:40
uint256 hashBlock
Definition: coinstats.h:31
CAmount nTotalAmount
Definition: coinstats.h:37
CoinStatsHashType m_hash_type
Definition: coinstats.h:29
#define LOCK(cs)
Definition: sync.h:226
bool error(const char *fmt, const Args &... args)
Definition: system.h:49
assert(!tx.IsCoinBase())
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:12