Page MenuHomePhabricator

D14673.id42741.diff
No OneTemporary

D14673.id42741.diff

diff --git a/src/index/coinstatsindex.h b/src/index/coinstatsindex.h
--- a/src/index/coinstatsindex.h
+++ b/src/index/coinstatsindex.h
@@ -57,8 +57,8 @@
bool f_wipe = false);
// Look up stats for a specific block using CBlockIndex
- bool LookUpStats(const CBlockIndex *block_index,
- node::CCoinsStats &coins_stats) const;
+ std::optional<node::CCoinsStats>
+ LookUpStats(const CBlockIndex *block_index) const;
};
/// The global UTXO set hash object.
diff --git a/src/index/coinstatsindex.cpp b/src/index/coinstatsindex.cpp
--- a/src/index/coinstatsindex.cpp
+++ b/src/index/coinstatsindex.cpp
@@ -340,31 +340,35 @@
return db.Read(DBHashKey(block_index->GetBlockHash()), result);
}
-bool CoinStatsIndex::LookUpStats(const CBlockIndex *block_index,
- CCoinsStats &coins_stats) const {
+std::optional<CCoinsStats>
+CoinStatsIndex::LookUpStats(const CBlockIndex *block_index) const {
+ CCoinsStats stats{Assert(block_index)->nHeight,
+ block_index->GetBlockHash()};
+ stats.index_used = true;
+
DBVal entry;
if (!LookUpOne(*m_db, block_index, entry)) {
- return false;
+ return std::nullopt;
}
- coins_stats.hashSerialized = entry.muhash;
- coins_stats.nTransactionOutputs = entry.transaction_output_count;
- coins_stats.nBogoSize = entry.bogo_size;
- coins_stats.nTotalAmount = entry.total_amount;
- coins_stats.total_subsidy = entry.total_subsidy;
- coins_stats.total_unspendable_amount = entry.total_unspendable_amount;
- coins_stats.total_prevout_spent_amount = entry.total_prevout_spent_amount;
- coins_stats.total_new_outputs_ex_coinbase_amount =
+ stats.hashSerialized = entry.muhash;
+ stats.nTransactionOutputs = entry.transaction_output_count;
+ stats.nBogoSize = entry.bogo_size;
+ stats.nTotalAmount = entry.total_amount;
+ stats.total_subsidy = entry.total_subsidy;
+ stats.total_unspendable_amount = entry.total_unspendable_amount;
+ stats.total_prevout_spent_amount = entry.total_prevout_spent_amount;
+ stats.total_new_outputs_ex_coinbase_amount =
entry.total_new_outputs_ex_coinbase_amount;
- coins_stats.total_coinbase_amount = entry.total_coinbase_amount;
- coins_stats.total_unspendables_genesis_block =
+ stats.total_coinbase_amount = entry.total_coinbase_amount;
+ stats.total_unspendables_genesis_block =
entry.total_unspendables_genesis_block;
- coins_stats.total_unspendables_bip30 = entry.total_unspendables_bip30;
- coins_stats.total_unspendables_scripts = entry.total_unspendables_scripts;
- coins_stats.total_unspendables_unclaimed_rewards =
+ stats.total_unspendables_bip30 = entry.total_unspendables_bip30;
+ stats.total_unspendables_scripts = entry.total_unspendables_scripts;
+ stats.total_unspendables_unclaimed_rewards =
entry.total_unspendables_unclaimed_rewards;
- return true;
+ return stats;
}
bool CoinStatsIndex::Init() {
diff --git a/src/node/coinstats.h b/src/node/coinstats.h
--- a/src/node/coinstats.h
+++ b/src/node/coinstats.h
@@ -71,6 +71,9 @@
//! Total cumulative amount of coins lost due to unclaimed miner rewards up
//! to and including this block
Amount total_unspendables_unclaimed_rewards{Amount::zero()};
+
+ CCoinsStats() = default;
+ CCoinsStats(int block_height, const BlockHash &block_hash);
};
/**
@@ -88,6 +91,11 @@
uint64_t GetBogoSize(const CScript &script_pub_key);
CDataStream TxOutSer(const COutPoint &outpoint, const Coin &coin);
+
+std::optional<CCoinsStats>
+ComputeUTXOStats(CoinStatsHashType hash_type, CCoinsView *view,
+ BlockManager &blockman,
+ const std::function<void()> &interruption_point = {});
} // namespace node
#endif // BITCOIN_NODE_COINSTATS_H
diff --git a/src/node/coinstats.cpp b/src/node/coinstats.cpp
--- a/src/node/coinstats.cpp
+++ b/src/node/coinstats.cpp
@@ -19,6 +19,9 @@
#include <map>
namespace node {
+CCoinsStats::CCoinsStats(int block_height, const BlockHash &block_hash)
+ : nHeight(block_height), hashBlock(block_hash) {}
+
uint64_t GetBogoSize(const CScript &script_pub_key) {
return 32 /* txid */ + 4 /* vout index */ + 4 /* height + coinbase */ +
8 /* amount */ + 2 /* scriptPubKey len */ +
@@ -89,30 +92,11 @@
//! 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);
TxId prevkey;
@@ -143,34 +127,32 @@
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) {
- CCoinsStats stats{};
+ComputeUTXOStats(CoinStatsHashType hash_type, CCoinsView *view,
+ BlockManager &blockman,
+ const std::function<void()> &interruption_point) {
+ 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);
@@ -199,4 +181,33 @@
stats.hashSerialized = out;
}
static void FinalizeHash(std::nullptr_t, CCoinsStats &stats) {}
+
+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 g_coin_stats_index->LookUpStats(pindex);
+ } else {
+ CBlockIndex *block_index = WITH_LOCK(
+ ::cs_main,
+ return blockman.LookupBlockIndex(view->GetBestBlock()));
+ return g_coin_stats_index->LookUpStats(block_index);
+ }
+ }
+
+ // 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/test/coinstatsindex_tests.cpp b/src/test/coinstatsindex_tests.cpp
--- a/src/test/coinstatsindex_tests.cpp
+++ b/src/test/coinstatsindex_tests.cpp
@@ -32,7 +32,6 @@
BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup) {
CoinStatsIndex coin_stats_index{1 << 20, true};
- CCoinsStats coin_stats{};
const CBlockIndex *block_index;
{
LOCK(cs_main);
@@ -40,7 +39,7 @@
}
// CoinStatsIndex should not be found before it is started.
- BOOST_CHECK(!coin_stats_index.LookUpStats(block_index, coin_stats));
+ BOOST_CHECK(!coin_stats_index.LookUpStats(block_index));
// BlockUntilSyncedToCurrentChain should return false before CoinStatsIndex
// is started.
@@ -56,10 +55,10 @@
LOCK(cs_main);
genesis_block_index = m_node.chainman->ActiveChain().Genesis();
}
- BOOST_CHECK(coin_stats_index.LookUpStats(genesis_block_index, coin_stats));
+ BOOST_CHECK(coin_stats_index.LookUpStats(genesis_block_index));
// Check that CoinStatsIndex updates with new blocks.
- coin_stats_index.LookUpStats(block_index, coin_stats);
+ BOOST_CHECK(coin_stats_index.LookUpStats(block_index));
const CScript script_pub_key{
CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG};
@@ -69,13 +68,12 @@
// Let the CoinStatsIndex to catch up again.
BOOST_CHECK(coin_stats_index.BlockUntilSyncedToCurrentChain());
- CCoinsStats new_coin_stats{};
const CBlockIndex *new_block_index;
{
LOCK(cs_main);
new_block_index = m_node.chainman->ActiveTip();
}
- coin_stats_index.LookUpStats(new_block_index, new_coin_stats);
+ BOOST_CHECK(coin_stats_index.LookUpStats(new_block_index));
BOOST_CHECK(block_index != new_block_index);
diff --git a/src/validation.cpp b/src/validation.cpp
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -70,10 +70,10 @@
using node::BlockMap;
using node::CCoinsStats;
using node::CoinStatsHashType;
+using node::ComputeUTXOStats;
using node::fImporting;
using node::fPruneMode;
using node::fReindex;
-using node::GetUTXOStats;
using node::nPruneTarget;
using node::OpenBlockFile;
using node::ReadBlockFromDisk;
@@ -5987,7 +5987,7 @@
::cs_main, return m_blockman.LookupBlockIndex(base_blockhash));
if (!snapshot_start_block) {
- // Needed for GetUTXOStats and ExpectedAssumeutxo to determine the
+ // Needed for ComputeUTXOStats and ExpectedAssumeutxo to determine the
// height and to avoid a crash when base_blockhash.IsNull()
LogPrintf("[snapshot] Did not find snapshot start blockheader %s\n",
base_blockhash.ToString());
@@ -6112,8 +6112,8 @@
WITH_LOCK(::cs_main, return &snapshot_chainstate.CoinsDB());
const std::optional<CCoinsStats> maybe_stats =
- GetUTXOStats(snapshot_coinsdb, m_blockman,
- CoinStatsHashType::HASH_SERIALIZED, breakpoint_fnc);
+ ComputeUTXOStats(CoinStatsHashType::HASH_SERIALIZED, snapshot_coinsdb,
+ m_blockman, breakpoint_fnc);
if (!maybe_stats.has_value()) {
LogPrintf("[snapshot] failed to generate coins stats\n");
return false;

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 26, 10:34 (5 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5572323
Default Alt Text
D14673.id42741.diff (12 KB)

Event Timeline