In f3bf63ec4f028cf9ee0820226f44fcbe26d358c9 “kernel: acquire coinstats cursor and block info atomically”
stats was being generated partially in both these ComputeUTXOStats functions, which reads oddly to me. Now that the pcursor is also moved and passed to this function, which reads oddly as well, I believe we can refactor this function in this PR to completely build the stats inside this function.
A side benefit is that by removing the stats and pcursor arguments, the function signature becomes quite similar to its namesake, which in turn becomes a straightforward wrapper of this function.
Builds fine, unit tests pass.
0diff --git a/src/kernel/coinstats.cpp b/src/kernel/coinstats.cpp
1index 49b51d64f3..69c4b44f2f 100644
2--- a/src/kernel/coinstats.cpp
3+++ b/src/kernel/coinstats.cpp
4@@ -109,9 +109,17 @@ static void ApplyStats(CCoinsStats& stats, const std::map<uint32_t, Coin>& outpu
5
6 //! Calculate statistics about the unspent transaction output set
7 template <typename T>
8-static bool ComputeUTXOStats(CCoinsView* view, CCoinsStats& stats, T hash_obj, const std::function<void()>& interruption_point, std::unique_ptr<CCoinsViewCursor> pcursor)
9+static std::optional<CCoinsStats> ComputeUTXOStats(T hash_obj, CCoinsView* view, node::BlockManager& blockman, const std::function<void()>& interruption_point)
10 {
11+ std::unique_ptr<CCoinsViewCursor> pcursor;
12+ CBlockIndex* pindex;
13+ {
14+ LOCK(::cs_main);
15+ pcursor = view->Cursor();
16+ pindex = blockman.LookupBlockIndex(pcursor->GetBestBlock());
17+ }
18 assert(pcursor);
19+ CCoinsStats stats{Assert(pindex)->nHeight, pindex->GetBlockHash()};
20
21 Txid prevkey;
22 std::map<uint32_t, Coin> outputs;
23@@ -130,7 +138,7 @@ static bool ComputeUTXOStats(CCoinsView* view, CCoinsStats& stats, T hash_obj, c
24 stats.coins_count++;
25 } else {
26 LogError("%s: unable to read value\n", __func__);
27- return false;
28+ return std::nullopt;
29 }
30 pcursor->Next();
31 }
32@@ -142,42 +150,27 @@ static bool ComputeUTXOStats(CCoinsView* view, CCoinsStats& stats, T hash_obj, c
33 FinalizeHash(hash_obj, stats);
34
35 stats.nDiskSize = view->EstimateSize();
36-
37- return true;
38+ return stats;
39 }
40
41 std::optional<CCoinsStats> ComputeUTXOStats(CoinStatsHashType hash_type, CCoinsView* view, node::BlockManager& blockman, const std::function<void()>& interruption_point)
42 {
43- std::unique_ptr<CCoinsViewCursor> pcursor;
44- CBlockIndex* pindex;
45- {
46- LOCK(::cs_main);
47- pcursor = view->Cursor();
48- pindex = blockman.LookupBlockIndex(pcursor->GetBestBlock());
49- }
50- CCoinsStats stats{Assert(pindex)->nHeight, pindex->GetBlockHash()};
51-
52- bool success = [&]() -> bool {
53+ return [&]() -> std::optional<CCoinsStats> {
54 switch (hash_type) {
55 case(CoinStatsHashType::HASH_SERIALIZED): {
56 HashWriter ss{};
57- return ComputeUTXOStats(view, stats, ss, interruption_point, std::move(pcursor));
58+ return ComputeUTXOStats(ss, view, blockman, interruption_point);
59 }
60 case(CoinStatsHashType::MUHASH): {
61 MuHash3072 muhash;
62- return ComputeUTXOStats(view, stats, muhash, interruption_point, std::move(pcursor));
63+ return ComputeUTXOStats(muhash, view, blockman, interruption_point);
64 }
65 case(CoinStatsHashType::NONE): {
66- return ComputeUTXOStats(view, stats, nullptr, interruption_point, std::move(pcursor));
67+ return ComputeUTXOStats(nullptr, view, blockman, interruption_point);
68 }
69 } // no default case, so the compiler can warn about missing cases
70 assert(false);
71 }();
72-
73- if (!success) {
74- return std::nullopt;
75- }
76- return stats;
77 }
78
79 static void FinalizeHash(HashWriter& ss, CCoinsStats& stats)