What changed, and why it matters
This is a small internal code cleanup in Bitcoin Core. It changes several functions that compute UTXO (unspent transaction output) statistics so they accept a more specific database-view pointer instead of a generic one, because only the concrete database view actually supports cursor iteration. There is no user-visible behavior change and no security fix.
No security action needed; review as ordinary refactoring.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit narrows the type accepted by ComputeUTXOStats, GetUTXOStats, and the coins_view fuzz target from CCoinsView to CCoinsViewDB. It adds the txdb.h include in coinstats.cpp and updates the fuzz test to call Cursor() on the concrete db pointer rather than the abstract backend view. This is a refactoring step toward removing the abstract Cursor() hook, with no functional or security-relevant change evident in the diff.
Changed components
src/kernel/coinstats.cppsrc/kernel/coinstats.hsrc/rpc/blockchain.cppsrc/test/fuzz/coins_view.cppInspect captured patch +8 / −7
diff --git a/src/kernel/coinstats.cpp b/src/kernel/coinstats.cpp
index 4f2f3fea..66fcd983 100644
--- a/src/kernel/coinstats.cpp
+++ b/src/kernel/coinstats.cpp
@@ -14,6 +14,7 @@
#include <span.h>
#include <streams.h>
#include <sync.h>
+#include <txdb.h>
#include <uint256.h>
#include <util/check.h>
#include <util/log.h>
@@ -108,7 +109,7 @@ static void ApplyStats(CCoinsStats& stats, const std::map<uint32_t, Coin>& outpu
//! Calculate statistics about the unspent transaction output set
template <typename T>
-static std::optional<CCoinsStats> ComputeUTXOStats(T hash_obj, CCoinsView* view, node::BlockManager& blockman, const std::function<void()>& interruption_point)
+static std::optional<CCoinsStats> ComputeUTXOStats(T hash_obj, CCoinsViewDB* view, node::BlockManager& blockman, const std::function<void()>& interruption_point)
{
std::unique_ptr<CCoinsViewCursor> pcursor;
CBlockIndex* pindex;
@@ -152,7 +153,7 @@ static std::optional<CCoinsStats> ComputeUTXOStats(T hash_obj, CCoinsView* view,
return stats;
}
-std::optional<CCoinsStats> ComputeUTXOStats(CoinStatsHashType hash_type, CCoinsView* view, node::BlockManager& blockman, const std::function<void()>& interruption_point)
+std::optional<CCoinsStats> ComputeUTXOStats(CoinStatsHashType hash_type, CCoinsViewDB* view, node::BlockManager& blockman, const std::function<void()>& interruption_point)
{
return [&]() -> std::optional<CCoinsStats> {
switch (hash_type) {
diff --git a/src/kernel/coinstats.h b/src/kernel/coinstats.h
index 92ace06b..0f0f4628 100644
--- a/src/kernel/coinstats.h
+++ b/src/kernel/coinstats.h
@@ -13,7 +13,7 @@
#include <functional>
#include <optional>
-class CCoinsView;
+class CCoinsViewDB;
class Coin;
class COutPoint;
class CScript;
@@ -77,7 +77,7 @@ uint64_t GetBogoSize(const CScript& script_pub_key);
void ApplyCoinHash(MuHash3072& muhash, const COutPoint& outpoint, const Coin& coin);
void RemoveCoinHash(MuHash3072& muhash, const COutPoint& outpoint, const Coin& coin);
-std::optional<CCoinsStats> ComputeUTXOStats(CoinStatsHashType hash_type, CCoinsView* view, node::BlockManager& blockman, const std::function<void()>& interruption_point = {});
+std::optional<CCoinsStats> ComputeUTXOStats(CoinStatsHashType hash_type, CCoinsViewDB* view, node::BlockManager& blockman, const std::function<void()>& interruption_point = {});
} // namespace kernel
#endif // BITCOIN_KERNEL_COINSTATS_H
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index d78b82bc..f6e7ba28 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -992,7 +992,7 @@ CoinStatsHashType ParseHashType(std::string_view hash_type_input)
*
* @param[in] index_requested Signals if the coinstatsindex should be used (when available).
*/
-static std::optional<kernel::CCoinsStats> GetUTXOStats(CCoinsView* view, node::BlockManager& blockman,
+static std::optional<kernel::CCoinsStats> GetUTXOStats(CCoinsViewDB* view, node::BlockManager& blockman,
kernel::CoinStatsHashType hash_type,
const std::function<void()>& interruption_point = {},
const CBlockIndex* pindex = nullptr,
@@ -1083,7 +1083,7 @@ static RPCMethod gettxoutsetinfo()
Chainstate& active_chainstate = chainman.ActiveChainstate();
active_chainstate.ForceFlushStateToDisk(/*wipe_cache=*/false);
- CCoinsView* coins_view;
+ CCoinsViewDB* coins_view;
BlockManager* blockman;
{
LOCK(::cs_main);
diff --git a/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp
index db81e190..6116150e 100644
--- a/src/test/fuzz/coins_view.cpp
+++ b/src/test/fuzz/coins_view.cpp
@@ -244,7 +244,7 @@ void TestCoinsView(FuzzedDataProvider& fuzzed_data_provider, CCoinsViewCache& co
{
if (is_db && backend_coins_view == original_backend) {
- assert(backend_coins_view->Cursor());
+ assert(db->Cursor());
}
(void)backend_coins_view->EstimateSize();
(void)backend_coins_view->GetBestBlock();
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.