makes sense. but might be nice to hold cs_main till we construct the cursor like it’s done in PrepareUTXOSnapshot just for guarantee that everything is based on same tip?
also since blocks can now arrive when we’re running dumptxoutset - it’s possible that the chain tip of 1st temp_cache is one height while the chain tip of rollback_cache is another height.
ex: my chaintip was at 828106 and did a rollback to 828090 but during that process my chaintip became 828172 (IBD 🫣)
so for any block from 828172 (new chain tip) to 828106 (old chain tip) - we apparently did some additional no-op work which could be skipped if we just use the same chain tip throughout:
02026-03-31T18:01:09Z ### DISCONNECT_UNCLEAN at height 828130
12026-03-31T18:01:09Z ### flushing height 828130 (should be no-op)
22026-03-31T18:01:09Z Rolled back 53% of blocks.
something like this might help keep stuff consistent:
0index 305dd782ba..58bc066171 100644
1--- a/src/rpc/blockchain.cpp
2+++ b/src/rpc/blockchain.cpp
3@@ -3221,14 +3221,18 @@ UniValue CreateRolledBackUTXOSnapshot(
4 CoinsViewOptions{}
5 );
6
7+ const CBlockIndex* tip = nullptr;
8 LogInfo("Copying current UTXO set to temporary database.");
9 {
10- WITH_LOCK(::cs_main, chainstate.ForceFlushStateToDisk(/*wipe_cache=*/false));
11 CCoinsViewCache temp_cache(temp_db.get());
12- temp_cache.SetBestBlock(chainstate.m_chain.Tip()->GetBlockHash());
13-
14 std::unique_ptr<CCoinsViewCursor> cursor;
15- WITH_LOCK(::cs_main, cursor = chainstate.CoinsDB().Cursor());
16+ {
17+ LOCK(::cs_main);
18+ tip = chainstate.m_chain.Tip();
19+ chainstate.ForceFlushStateToDisk(/*wipe_cache=*/false);
20+ cursor = chainstate.CoinsDB().Cursor();
21+ }
22+ temp_cache.SetBestBlock(tip->GetBlockHash());
23
24 size_t coins_count = 0;
25 while (cursor->Valid()) {
26@@ -3257,9 +3261,9 @@ UniValue CreateRolledBackUTXOSnapshot(
27 LogInfo("UTXO set copy complete: %u coins total", coins_count);
28 }
29
30- LogInfo("Rolling back from height %d to %d", chainstate.m_chain.Tip()->nHeight, target->nHeight);
31+ LogInfo("Rolling back from height %d to %d", tip->nHeight, target->nHeight);
32
33- const CBlockIndex* block_index{chainstate.m_chain.Tip()};
34+ const CBlockIndex* block_index{tip};
35 const size_t total_blocks{static_cast<size_t>(block_index->nHeight - target->nHeight)};
36 CCoinsViewCache rollback_cache(temp_db.get());
37 rollback_cache.SetBestBlock(block_index->GetBlockHash());