|
19 | 19 | #include <map>
|
20 | 20 |
|
21 | 21 | namespace node {
|
| 22 | + |
| 23 | +CCoinsStats::CCoinsStats(int block_height, const uint256& block_hash) |
| 24 | + : nHeight(block_height), |
| 25 | + hashBlock(block_hash) {} |
| 26 | + |
22 | 27 | // Database-independent metric indicating the UTXO set size
|
23 | 28 | uint64_t GetBogoSize(const CScript& script_pub_key)
|
24 | 29 | {
|
@@ -94,24 +99,11 @@ static void ApplyStats(CCoinsStats& stats, const uint256& hash, const std::map<u
|
94 | 99 |
|
95 | 100 | //! Calculate statistics about the unspent transaction output set
|
96 | 101 | template <typename T>
|
97 |
| -static bool GetUTXOStats(CCoinsView* view, BlockManager& blockman, CCoinsStats& stats, T hash_obj, const std::function<void()>& interruption_point, const CBlockIndex* pindex, CoinStatsHashType& hash_type, bool index_requested) |
| 102 | +static bool ComputeUTXOStats(CCoinsView* view, CCoinsStats& stats, T hash_obj, const std::function<void()>& interruption_point) |
98 | 103 | {
|
99 | 104 | std::unique_ptr<CCoinsViewCursor> pcursor(view->Cursor());
|
100 | 105 | assert(pcursor);
|
101 | 106 |
|
102 |
| - if (!pindex) { |
103 |
| - LOCK(cs_main); |
104 |
| - pindex = blockman.LookupBlockIndex(view->GetBestBlock()); |
105 |
| - } |
106 |
| - stats.nHeight = Assert(pindex)->nHeight; |
107 |
| - stats.hashBlock = pindex->GetBlockHash(); |
108 |
| - |
109 |
| - // Use CoinStatsIndex if it is requested and available and a hash_type of Muhash or None was requested |
110 |
| - if ((hash_type == CoinStatsHashType::MUHASH || hash_type == CoinStatsHashType::NONE) && g_coin_stats_index && index_requested) { |
111 |
| - stats.index_used = true; |
112 |
| - return g_coin_stats_index->LookUpStats(pindex, stats); |
113 |
| - } |
114 |
| - |
115 | 107 | PrepareHash(hash_obj, stats);
|
116 | 108 |
|
117 | 109 | uint256 prevkey;
|
@@ -142,25 +134,27 @@ static bool GetUTXOStats(CCoinsView* view, BlockManager& blockman, CCoinsStats&
|
142 | 134 | FinalizeHash(hash_obj, stats);
|
143 | 135 |
|
144 | 136 | stats.nDiskSize = view->EstimateSize();
|
| 137 | + |
145 | 138 | return true;
|
146 | 139 | }
|
147 | 140 |
|
148 |
| -std::optional<CCoinsStats> GetUTXOStats(CCoinsView* view, BlockManager& blockman, CoinStatsHashType hash_type, const std::function<void()>& interruption_point, const CBlockIndex* pindex, bool index_requested) |
| 141 | +std::optional<CCoinsStats> ComputeUTXOStats(CoinStatsHashType hash_type, CCoinsView* view, BlockManager& blockman, const std::function<void()>& interruption_point) |
149 | 142 | {
|
150 |
| - CCoinsStats stats{}; |
| 143 | + CBlockIndex* pindex = WITH_LOCK(::cs_main, return blockman.LookupBlockIndex(view->GetBestBlock())); |
| 144 | + CCoinsStats stats{Assert(pindex)->nHeight, pindex->GetBlockHash()}; |
151 | 145 |
|
152 | 146 | bool success = [&]() -> bool {
|
153 | 147 | switch (hash_type) {
|
154 | 148 | case(CoinStatsHashType::HASH_SERIALIZED): {
|
155 | 149 | CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
|
156 |
| - return GetUTXOStats(view, blockman, stats, ss, interruption_point, pindex, hash_type, index_requested); |
| 150 | + return ComputeUTXOStats(view, stats, ss, interruption_point); |
157 | 151 | }
|
158 | 152 | case(CoinStatsHashType::MUHASH): {
|
159 | 153 | MuHash3072 muhash;
|
160 |
| - return GetUTXOStats(view, blockman, stats, muhash, interruption_point, pindex, hash_type, index_requested); |
| 154 | + return ComputeUTXOStats(view, stats, muhash, interruption_point); |
161 | 155 | }
|
162 | 156 | case(CoinStatsHashType::NONE): {
|
163 |
| - return GetUTXOStats(view, blockman, stats, nullptr, interruption_point, pindex, hash_type, index_requested); |
| 157 | + return ComputeUTXOStats(view, stats, nullptr, interruption_point); |
164 | 158 | }
|
165 | 159 | } // no default case, so the compiler can warn about missing cases
|
166 | 160 | assert(false);
|
@@ -192,4 +186,43 @@ static void FinalizeHash(MuHash3072& muhash, CCoinsStats& stats)
|
192 | 186 | stats.hashSerialized = out;
|
193 | 187 | }
|
194 | 188 | static void FinalizeHash(std::nullptr_t, CCoinsStats& stats) {}
|
| 189 | + |
| 190 | +std::optional<CCoinsStats> LookupUTXOStatsWithIndex(CoinStatsIndex& coin_stats_index, const CBlockIndex* pindex) |
| 191 | +{ |
| 192 | + CCoinsStats stats{Assert(pindex)->nHeight, pindex->GetBlockHash()}; |
| 193 | + |
| 194 | + stats.index_used = true; |
| 195 | + if (!coin_stats_index.LookUpStats(pindex, stats)) { |
| 196 | + return std::nullopt; |
| 197 | + } |
| 198 | + |
| 199 | + return stats; |
| 200 | +} |
| 201 | + |
| 202 | +std::optional<CCoinsStats> LookupUTXOStatsWithIndex(CoinStatsIndex& coin_stats_index, CCoinsView* view, BlockManager& blockman) |
| 203 | +{ |
| 204 | + CBlockIndex* pindex = WITH_LOCK(::cs_main, return blockman.LookupBlockIndex(view->GetBestBlock())); |
| 205 | + |
| 206 | + return LookupUTXOStatsWithIndex(coin_stats_index, pindex); |
| 207 | +} |
| 208 | + |
| 209 | +std::optional<CCoinsStats> GetUTXOStats(CCoinsView* view, BlockManager& blockman, CoinStatsHashType hash_type, const std::function<void()>& interruption_point, const CBlockIndex* pindex, bool index_requested) |
| 210 | +{ |
| 211 | + // Use CoinStatsIndex if it is requested and available and a hash_type of Muhash or None was requested |
| 212 | + if ((hash_type == CoinStatsHashType::MUHASH || hash_type == CoinStatsHashType::NONE) && g_coin_stats_index && index_requested) { |
| 213 | + if (pindex) { |
| 214 | + return LookupUTXOStatsWithIndex(*g_coin_stats_index, pindex); |
| 215 | + } else { |
| 216 | + return LookupUTXOStatsWithIndex(*g_coin_stats_index, view, blockman); |
| 217 | + } |
| 218 | + } |
| 219 | + |
| 220 | + // If the coinstats index isn't requested or is otherwise not usable, the |
| 221 | + // pindex should either be null or equal to the view's best block. This is |
| 222 | + // because without the coinstats index we can only get coinstats about the |
| 223 | + // best block. |
| 224 | + assert(!pindex || pindex->GetBlockHash() == view->GetBestBlock()); |
| 225 | + |
| 226 | + return ComputeUTXOStats(hash_type, view, blockman, interruption_point); |
| 227 | +} |
195 | 228 | } // namespace node
|
0 commit comments