Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13711105
D14673.id42741.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
12 KB
Subscribers
None
D14673.id42741.diff
View Options
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
Details
Attached
Mime Type
text/plain
Expires
Sat, Apr 26, 10:34 (1 h, 12 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5572323
Default Alt Text
D14673.id42741.diff (12 KB)
Attached To
D14673: coinstats: Separate hasher/index lookup codepaths
Event Timeline
Log In to Comment