Bitcoin Core 31.0.0
P2P Digital Currency
Loading...
Searching...
No Matches
coinstats.cpp
Go to the documentation of this file.
1// Copyright (c) 2022-present 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 <kernel/coinstats.h>
6
7#include <chain.h>
8#include <coins.h>
9#include <crypto/muhash.h>
10#include <hash.h>
11#include <node/blockstorage.h>
13#include <script/script.h>
14#include <span.h>
15#include <streams.h>
16#include <sync.h>
17#include <uint256.h>
18#include <util/check.h>
19#include <util/log.h>
20#include <util/overflow.h>
21#include <validation.h>
22
23#include <map>
24#include <memory>
25#include <span>
26#include <utility>
27#include <version>
28
29namespace kernel {
30
31CCoinsStats::CCoinsStats(int block_height, const uint256& block_hash)
32 : nHeight(block_height),
33 hashBlock(block_hash) {}
34
35// Database-independent metric indicating the UTXO set size
36uint64_t GetBogoSize(const CScript& script_pub_key)
37{
38 return 32 /* txid */ +
39 4 /* vout index */ +
40 4 /* height + coinbase */ +
41 8 /* amount */ +
42 2 /* scriptPubKey len */ +
43 script_pub_key.size() /* scriptPubKey */;
44}
45
46template <typename T>
47static void TxOutSer(T& ss, const COutPoint& outpoint, const Coin& coin)
48{
49 ss << outpoint;
51 ss << coin.out;
52}
53
54static void ApplyCoinHash(HashWriter& ss, const COutPoint& outpoint, const Coin& coin)
55{
56 TxOutSer(ss, outpoint, coin);
57}
58
59void ApplyCoinHash(MuHash3072& muhash, const COutPoint& outpoint, const Coin& coin)
60{
61 DataStream ss{};
62 TxOutSer(ss, outpoint, coin);
63 muhash.Insert(MakeUCharSpan(ss));
64}
65
66void RemoveCoinHash(MuHash3072& muhash, const COutPoint& outpoint, const Coin& coin)
67{
68 DataStream ss{};
69 TxOutSer(ss, outpoint, coin);
70 muhash.Remove(MakeUCharSpan(ss));
71}
72
73static void ApplyCoinHash(std::nullptr_t, const COutPoint& outpoint, const Coin& coin) {}
74
87template <typename T>
88static void ApplyHash(T& hash_obj, const Txid& hash, const std::map<uint32_t, Coin>& outputs)
89{
90 for (auto it = outputs.begin(); it != outputs.end(); ++it) {
91 COutPoint outpoint = COutPoint(hash, it->first);
92 Coin coin = it->second;
93 ApplyCoinHash(hash_obj, outpoint, coin);
94 }
95}
96
97static void ApplyStats(CCoinsStats& stats, const std::map<uint32_t, Coin>& outputs)
98{
99 assert(!outputs.empty());
100 stats.nTransactions++;
101 for (auto it = outputs.begin(); it != outputs.end(); ++it) {
102 stats.nTransactionOutputs++;
103 if (stats.total_amount.has_value()) {
104 stats.total_amount = CheckedAdd(*stats.total_amount, it->second.out.nValue);
105 }
106 stats.nBogoSize += GetBogoSize(it->second.out.scriptPubKey);
107 }
108}
109
111template <typename T>
112static bool ComputeUTXOStats(CCoinsView* view, CCoinsStats& stats, T hash_obj, const std::function<void()>& interruption_point, std::unique_ptr<CCoinsViewCursor> pcursor)
113{
114 assert(pcursor);
115
116 Txid prevkey;
117 std::map<uint32_t, Coin> outputs;
118 while (pcursor->Valid()) {
119 if (interruption_point) interruption_point();
120 COutPoint key;
121 Coin coin;
122 if (pcursor->GetKey(key) && pcursor->GetValue(coin)) {
123 if (!outputs.empty() && key.hash != prevkey) {
124 ApplyStats(stats, outputs);
125 ApplyHash(hash_obj, prevkey, outputs);
126 outputs.clear();
127 }
128 prevkey = key.hash;
129 outputs[key.n] = std::move(coin);
130 stats.coins_count++;
131 } else {
132 LogError("%s: unable to read value\n", __func__);
133 return false;
134 }
135 pcursor->Next();
136 }
137 if (!outputs.empty()) {
138 ApplyStats(stats, outputs);
139 ApplyHash(hash_obj, prevkey, outputs);
140 }
141
142 FinalizeHash(hash_obj, stats);
143
144 stats.nDiskSize = view->EstimateSize();
145
146 return true;
147}
148
149std::optional<CCoinsStats> ComputeUTXOStats(CoinStatsHashType hash_type, CCoinsView* view, node::BlockManager& blockman, const std::function<void()>& interruption_point)
150{
151 std::unique_ptr<CCoinsViewCursor> pcursor;
152 CBlockIndex* pindex;
153 {
155 pcursor = view->Cursor();
156 pindex = blockman.LookupBlockIndex(pcursor->GetBestBlock());
157 }
158 CCoinsStats stats{Assert(pindex)->nHeight, pindex->GetBlockHash()};
159
160 bool success = [&]() -> bool {
161 switch (hash_type) {
163 HashWriter ss{};
164 return ComputeUTXOStats(view, stats, ss, interruption_point, std::move(pcursor));
165 }
167 MuHash3072 muhash;
168 return ComputeUTXOStats(view, stats, muhash, interruption_point, std::move(pcursor));
169 }
171 return ComputeUTXOStats(view, stats, nullptr, interruption_point, std::move(pcursor));
172 }
173 } // no default case, so the compiler can warn about missing cases
174 assert(false);
175 }();
176
177 if (!success) {
178 return std::nullopt;
179 }
180 return stats;
181}
182
184{
185 stats.hashSerialized = ss.GetHash();
186}
187static void FinalizeHash(MuHash3072& muhash, CCoinsStats& stats)
188{
189 uint256 out;
190 muhash.Finalize(out);
191 stats.hashSerialized = out;
192}
193static void FinalizeHash(std::nullptr_t, CCoinsStats& stats) {}
194
195} // namespace kernel
#define Assert(val)
Identity function.
Definition check.h:113
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition chain.h:94
uint256 GetBlockHash() const
Definition chain.h:198
Abstract view on the open txout dataset.
Definition coins.h:308
virtual size_t EstimateSize() const
Estimate database size (0 if not implemented).
Definition coins.h:342
virtual std::unique_ptr< CCoinsViewCursor > Cursor() const
Get a cursor to iterate over the whole state.
Definition coins.cpp:26
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition transaction.h:29
uint32_t n
Definition transaction.h:32
Serialized script, used inside transaction inputs and outputs.
Definition script.h:405
A UTXO entry.
Definition coins.h:35
CTxOut out
unspent transaction output
Definition coins.h:38
uint32_t nHeight
at which height this containing transaction was included in the active block chain
Definition coins.h:44
unsigned int fCoinBase
whether containing transaction was a coinbase
Definition coins.h:41
Double ended buffer combining vector and stream-like interfaces.
Definition streams.h:133
A writer stream (for serialization) that computes a 256-bit hash.
Definition hash.h:101
A class representing MuHash sets.
Definition muhash.h:103
void Finalize(uint256 &out) noexcept
Definition muhash.cpp:552
MuHash3072 & Insert(std::span< const unsigned char > in) noexcept
Definition muhash.cpp:577
MuHash3072 & Remove(std::span< const unsigned char > in) noexcept
Definition muhash.cpp:582
Maintains a tree of blocks (stored in m_block_index) which is consulted to determine where the most-w...
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
size_type size() const
Definition prevector.h:247
256-bit opaque blob.
Definition uint256.h:195
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition cs_main.cpp:8
#define T(expected, seed, data)
#define LogError(...)
Definition log.h:97
static void FinalizeHash(HashWriter &ss, CCoinsStats &stats)
static void ApplyStats(CCoinsStats &stats, const std::map< uint32_t, Coin > &outputs)
Definition coinstats.cpp:97
static bool ComputeUTXOStats(CCoinsView *view, CCoinsStats &stats, T hash_obj, const std::function< void()> &interruption_point, std::unique_ptr< CCoinsViewCursor > pcursor)
Calculate statistics about the unspent transaction output set.
void RemoveCoinHash(MuHash3072 &muhash, const COutPoint &outpoint, const Coin &coin)
Definition coinstats.cpp:66
CoinStatsHashType
Definition coinstats.h:26
static void ApplyCoinHash(HashWriter &ss, const COutPoint &outpoint, const Coin &coin)
Definition coinstats.cpp:54
static void ApplyHash(T &hash_obj, const Txid &hash, const std::map< uint32_t, Coin > &outputs)
Definition coinstats.cpp:88
uint64_t GetBogoSize(const CScript &script_pub_key)
Definition coinstats.cpp:36
static void TxOutSer(T &ss, const COutPoint &outpoint, const Coin &coin)
Definition coinstats.cpp:47
std::optional< T > CheckedAdd(const T i, const T j) noexcept
Definition overflow.h:26
constexpr auto MakeUCharSpan(const V &v) -> decltype(UCharSpanCast(std::span{v}))
Like the std::span constructor, but for (const) unsigned char member types only.
Definition span.h:111
std::optional< CAmount > total_amount
The total amount, or nullopt if an overflow occurred calculating it.
Definition coinstats.h:41
uint64_t coins_count
The number of coins contained.
Definition coinstats.h:44
uint64_t nTransactions
Definition coinstats.h:35
uint64_t nTransactionOutputs
Definition coinstats.h:36
uint256 hashSerialized
Definition coinstats.h:38
#define LOCK(cs)
Definition sync.h:258
transaction_identifier< false > Txid
Txid commits to all transaction fields except the witness.
DataStream ss
assert(!tx.IsCoinBase())