aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/node/coinstats.cpp71
-rw-r--r--src/node/coinstats.h3
2 files changed, 55 insertions, 19 deletions
diff --git a/src/node/coinstats.cpp b/src/node/coinstats.cpp
index 8fc53fe172..26badd6eb2 100644
--- a/src/node/coinstats.cpp
+++ b/src/node/coinstats.cpp
@@ -19,6 +19,11 @@
#include <map>
namespace node {
+
+CCoinsStats::CCoinsStats(int block_height, const uint256& block_hash)
+ : nHeight(block_height),
+ hashBlock(block_hash) {}
+
// Database-independent metric indicating the UTXO set size
uint64_t GetBogoSize(const CScript& script_pub_key)
{
@@ -94,24 +99,11 @@ static void ApplyStats(CCoinsStats& stats, const uint256& hash, const std::map<u
//! Calculate statistics about the unspent transaction output set
template <typename T>
-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)
+static bool ComputeUTXOStats(CCoinsView* view, CCoinsStats& stats, T hash_obj, const std::function<void()>& interruption_point)
{
std::unique_ptr<CCoinsViewCursor> pcursor(view->Cursor());
assert(pcursor);
- if (!pindex) {
- LOCK(cs_main);
- pindex = blockman.LookupBlockIndex(view->GetBestBlock());
- }
- stats.nHeight = Assert(pindex)->nHeight;
- stats.hashBlock = pindex->GetBlockHash();
-
- // Use CoinStatsIndex if it is requested and available and a hash_type of Muhash or None was requested
- if ((hash_type == CoinStatsHashType::MUHASH || hash_type == CoinStatsHashType::NONE) && g_coin_stats_index && index_requested) {
- stats.index_used = true;
- return g_coin_stats_index->LookUpStats(pindex, stats);
- }
-
PrepareHash(hash_obj, stats);
uint256 prevkey;
@@ -142,25 +134,27 @@ static bool GetUTXOStats(CCoinsView* view, BlockManager& blockman, CCoinsStats&
FinalizeHash(hash_obj, stats);
stats.nDiskSize = view->EstimateSize();
+
return true;
}
-std::optional<CCoinsStats> GetUTXOStats(CCoinsView* view, BlockManager& blockman, CoinStatsHashType hash_type, const std::function<void()>& interruption_point, const CBlockIndex* pindex, bool index_requested)
+std::optional<CCoinsStats> ComputeUTXOStats(CoinStatsHashType hash_type, CCoinsView* view, BlockManager& blockman, const std::function<void()>& interruption_point)
{
- CCoinsStats stats{};
+ CBlockIndex* pindex = WITH_LOCK(::cs_main, return blockman.LookupBlockIndex(view->GetBestBlock()));
+ CCoinsStats stats{Assert(pindex)->nHeight, pindex->GetBlockHash()};
bool success = [&]() -> bool {
switch (hash_type) {
case(CoinStatsHashType::HASH_SERIALIZED): {
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
- return GetUTXOStats(view, blockman, stats, ss, interruption_point, pindex, hash_type, index_requested);
+ return ComputeUTXOStats(view, stats, ss, interruption_point);
}
case(CoinStatsHashType::MUHASH): {
MuHash3072 muhash;
- return GetUTXOStats(view, blockman, stats, muhash, interruption_point, pindex, hash_type, index_requested);
+ return ComputeUTXOStats(view, stats, muhash, interruption_point);
}
case(CoinStatsHashType::NONE): {
- return GetUTXOStats(view, blockman, stats, nullptr, interruption_point, pindex, hash_type, index_requested);
+ return ComputeUTXOStats(view, stats, nullptr, interruption_point);
}
} // no default case, so the compiler can warn about missing cases
assert(false);
@@ -192,4 +186,43 @@ static void FinalizeHash(MuHash3072& muhash, CCoinsStats& stats)
stats.hashSerialized = out;
}
static void FinalizeHash(std::nullptr_t, CCoinsStats& stats) {}
+
+std::optional<CCoinsStats> LookupUTXOStatsWithIndex(CoinStatsIndex& coin_stats_index, const CBlockIndex* pindex)
+{
+ CCoinsStats stats{Assert(pindex)->nHeight, pindex->GetBlockHash()};
+
+ stats.index_used = true;
+ if (!coin_stats_index.LookUpStats(pindex, stats)) {
+ return std::nullopt;
+ }
+
+ return stats;
+}
+
+std::optional<CCoinsStats> LookupUTXOStatsWithIndex(CoinStatsIndex& coin_stats_index, CCoinsView* view, BlockManager& blockman)
+{
+ CBlockIndex* pindex = WITH_LOCK(::cs_main, return blockman.LookupBlockIndex(view->GetBestBlock()));
+
+ return LookupUTXOStatsWithIndex(coin_stats_index, pindex);
+}
+
+std::optional<CCoinsStats> GetUTXOStats(CCoinsView* view, BlockManager& blockman, CoinStatsHashType hash_type, const std::function<void()>& interruption_point, const CBlockIndex* pindex, bool index_requested)
+{
+ // Use CoinStatsIndex if it is requested and available and a hash_type of Muhash or None was requested
+ if ((hash_type == CoinStatsHashType::MUHASH || hash_type == CoinStatsHashType::NONE) && g_coin_stats_index && index_requested) {
+ if (pindex) {
+ return LookupUTXOStatsWithIndex(*g_coin_stats_index, pindex);
+ } else {
+ return LookupUTXOStatsWithIndex(*g_coin_stats_index, view, blockman);
+ }
+ }
+
+ // If the coinstats index isn't requested or is otherwise not usable, the
+ // pindex should either be null or equal to the view's best block. This is
+ // because without the coinstats index we can only get coinstats about the
+ // best block.
+ assert(!pindex || pindex->GetBlockHash() == view->GetBestBlock());
+
+ return ComputeUTXOStats(hash_type, view, blockman, interruption_point);
+}
} // namespace node
diff --git a/src/node/coinstats.h b/src/node/coinstats.h
index 36cbf19f29..d74d70deb2 100644
--- a/src/node/coinstats.h
+++ b/src/node/coinstats.h
@@ -64,6 +64,9 @@ struct CCoinsStats {
CAmount total_unspendables_scripts{0};
//! Total cumulative amount of coins lost due to unclaimed miner rewards up to and including this block
CAmount total_unspendables_unclaimed_rewards{0};
+
+ CCoinsStats() = default;
+ CCoinsStats(int block_height, const uint256& block_hash);
};
/**