2
2
// Distributed under the MIT software license, see the accompanying
3
3
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
4
5
+ #include < chainparams.h>
5
6
#include < index/coinstatsindex.h>
6
7
#include < test/util/setup_common.h>
8
+ #include < test/util/validation.h>
7
9
#include < util/time.h>
8
10
#include < validation.h>
9
11
@@ -16,6 +18,17 @@ using node::CoinStatsHashType;
16
18
17
19
BOOST_AUTO_TEST_SUITE (coinstatsindex_tests)
18
20
21
+ static void IndexWaitSynced(BaseIndex& index)
22
+ {
23
+ // Allow the CoinStatsIndex to catch up with the block index that is syncing
24
+ // in a background thread.
25
+ const auto timeout = GetTime<std::chrono::seconds>() + 120s;
26
+ while (!index.BlockUntilSyncedToCurrentChain ()) {
27
+ BOOST_REQUIRE (timeout > GetTime<std::chrono::milliseconds>());
28
+ UninterruptibleSleep (100ms);
29
+ }
30
+ }
31
+
19
32
BOOST_FIXTURE_TEST_CASE (coinstatsindex_initial_sync, TestChain100Setup)
20
33
{
21
34
CoinStatsIndex coin_stats_index{1 << 20 , true };
@@ -36,13 +49,7 @@ BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
36
49
37
50
BOOST_REQUIRE (coin_stats_index.Start (m_node.chainman ->ActiveChainstate ()));
38
51
39
- // Allow the CoinStatsIndex to catch up with the block index that is syncing
40
- // in a background thread.
41
- const auto timeout = GetTime<std::chrono::seconds>() + 120s;
42
- while (!coin_stats_index.BlockUntilSyncedToCurrentChain ()) {
43
- BOOST_REQUIRE (timeout > GetTime<std::chrono::milliseconds>());
44
- UninterruptibleSleep (100ms);
45
- }
52
+ IndexWaitSynced (coin_stats_index);
46
53
47
54
// Check that CoinStatsIndex works for genesis block.
48
55
const CBlockIndex* genesis_block_index;
@@ -78,4 +85,44 @@ BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
78
85
// Rest of shutdown sequence and destructors happen in ~TestingSetup()
79
86
}
80
87
88
+ // Test shutdown between BlockConnected and ChainStateFlushed notifications,
89
+ // make sure index is not corrupted and is able to reload.
90
+ BOOST_FIXTURE_TEST_CASE (coinstatsindex_unclean_shutdown, TestChain100Setup)
91
+ {
92
+ CChainState& chainstate = Assert (m_node.chainman )->ActiveChainstate ();
93
+ const CChainParams& params = Params ();
94
+ {
95
+ CoinStatsIndex index{1 << 20 };
96
+ BOOST_REQUIRE (index.Start (chainstate));
97
+ IndexWaitSynced (index);
98
+ std::shared_ptr<const CBlock> new_block;
99
+ CBlockIndex* new_block_index = nullptr ;
100
+ {
101
+ const CScript script_pub_key{CScript () << ToByteVector (coinbaseKey.GetPubKey ()) << OP_CHECKSIG};
102
+ const CBlock block = this ->CreateBlock ({}, script_pub_key, chainstate);
103
+
104
+ new_block = std::make_shared<CBlock>(block);
105
+
106
+ LOCK (cs_main);
107
+ BlockValidationState state;
108
+ BOOST_CHECK (CheckBlock (block, state, params.GetConsensus ()));
109
+ BOOST_CHECK (chainstate.AcceptBlock (new_block, state, &new_block_index, true , nullptr , nullptr ));
110
+ CCoinsViewCache view (&chainstate.CoinsTip ());
111
+ BOOST_CHECK (chainstate.ConnectBlock (block, state, new_block_index, view));
112
+ }
113
+ // Send block connected notification, then stop the index without
114
+ // sending a chainstate flushed notification. Prior to #24138, this
115
+ // would cause the index to be corrupted and fail to reload.
116
+ ValidationInterfaceTest::BlockConnected (index, new_block, new_block_index);
117
+ index.Stop ();
118
+ }
119
+
120
+ {
121
+ CoinStatsIndex index{1 << 20 };
122
+ // Make sure the index can be loaded.
123
+ BOOST_REQUIRE (index.Start (chainstate));
124
+ index.Stop ();
125
+ }
126
+ }
127
+
81
128
BOOST_AUTO_TEST_SUITE_END ()
0 commit comments