Branch data Line data Source code
1 : : // Copyright (c) 2020-2022 The Bitcoin Core developers
2 : : // Distributed under the MIT software license, see the accompanying
3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 : :
5 : : #include <chainparams.h>
6 : : #include <index/coinstatsindex.h>
7 : : #include <interfaces/chain.h>
8 : : #include <kernel/coinstats.h>
9 : : #include <test/util/index.h>
10 : : #include <test/util/setup_common.h>
11 : : #include <test/util/validation.h>
12 : : #include <validation.h>
13 : :
14 : : #include <boost/test/unit_test.hpp>
15 : :
16 : : BOOST_AUTO_TEST_SUITE(coinstatsindex_tests)
17 : :
18 [ + - + - : 7 : BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
19 : : {
20 [ + - ]: 1 : CoinStatsIndex coin_stats_index{interfaces::MakeChain(m_node), 1 << 20, true};
21 [ + - + - : 2 : BOOST_REQUIRE(coin_stats_index.Init());
+ - + - ]
22 : :
23 : 1 : const CBlockIndex* block_index;
24 : 1 : {
25 [ + - ]: 1 : LOCK(cs_main);
26 [ + - + - : 2 : block_index = m_node.chainman->ActiveChain().Tip();
+ - ]
27 : 0 : }
28 : :
29 : : // CoinStatsIndex should not be found before it is started.
30 [ + - + - : 2 : BOOST_CHECK(!coin_stats_index.LookUpStats(*block_index));
+ - + - ]
31 : :
32 : : // BlockUntilSyncedToCurrentChain should return false before CoinStatsIndex
33 : : // is started.
34 [ + - + - : 2 : BOOST_CHECK(!coin_stats_index.BlockUntilSyncedToCurrentChain());
+ - ]
35 : :
36 [ + - + - : 2 : BOOST_REQUIRE(coin_stats_index.StartBackgroundSync());
+ - + - ]
37 : :
38 [ + - + - ]: 1 : IndexWaitSynced(coin_stats_index, *Assert(m_node.shutdown_signal));
39 : :
40 : : // Check that CoinStatsIndex works for genesis block.
41 : 1 : const CBlockIndex* genesis_block_index;
42 : 1 : {
43 [ + - ]: 1 : LOCK(cs_main);
44 [ + - + - : 2 : genesis_block_index = m_node.chainman->ActiveChain().Genesis();
+ - ]
45 : 0 : }
46 [ + - + - : 2 : BOOST_CHECK(coin_stats_index.LookUpStats(*genesis_block_index));
+ - + - ]
47 : :
48 : : // Check that CoinStatsIndex updates with new blocks.
49 [ + - + - : 2 : BOOST_CHECK(coin_stats_index.LookUpStats(*block_index));
+ - + - ]
50 : :
51 [ + - + - : 1 : const CScript script_pub_key{CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG};
+ - ]
52 : 1 : std::vector<CMutableTransaction> noTxns;
53 [ + - ]: 1 : CreateAndProcessBlock(noTxns, script_pub_key);
54 : :
55 : : // Let the CoinStatsIndex to catch up again.
56 [ + - + - : 2 : BOOST_CHECK(coin_stats_index.BlockUntilSyncedToCurrentChain());
+ - + - ]
57 : :
58 : 1 : const CBlockIndex* new_block_index;
59 : 1 : {
60 [ + - ]: 1 : LOCK(cs_main);
61 [ + - + - : 2 : new_block_index = m_node.chainman->ActiveChain().Tip();
+ - ]
62 : 0 : }
63 [ + - + - : 2 : BOOST_CHECK(coin_stats_index.LookUpStats(*new_block_index));
+ - + - ]
64 : :
65 [ + - + - : 2 : BOOST_CHECK(block_index != new_block_index);
+ - ]
66 : :
67 : : // It is not safe to stop and destroy the index until it finishes handling
68 : : // the last BlockConnected notification. The BlockUntilSyncedToCurrentChain()
69 : : // call above is sufficient to ensure this, but the
70 : : // SyncWithValidationInterfaceQueue() call below is also needed to ensure
71 : : // TSAN always sees the test thread waiting for the notification thread, and
72 : : // avoid potential false positive reports.
73 [ + - ]: 1 : m_node.validation_signals->SyncWithValidationInterfaceQueue();
74 : :
75 : : // Shutdown sequence (c.f. Shutdown() in init.cpp)
76 [ + - ]: 1 : coin_stats_index.Stop();
77 : 1 : }
78 : :
79 : : // Test shutdown between BlockConnected and ChainStateFlushed notifications,
80 : : // make sure index is not corrupted and is able to reload.
81 [ + - + - : 7 : BOOST_FIXTURE_TEST_CASE(coinstatsindex_unclean_shutdown, TestChain100Setup)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
82 : : {
83 : 1 : Chainstate& chainstate = Assert(m_node.chainman)->ActiveChainstate();
84 : 1 : const CChainParams& params = Params();
85 : 1 : {
86 [ + - ]: 1 : CoinStatsIndex index{interfaces::MakeChain(m_node), 1 << 20};
87 [ + - + - : 2 : BOOST_REQUIRE(index.Init());
+ - + - ]
88 [ + - + - : 2 : BOOST_REQUIRE(index.StartBackgroundSync());
+ - + - ]
89 [ + - + - ]: 1 : IndexWaitSynced(index, *Assert(m_node.shutdown_signal));
90 : 1 : std::shared_ptr<const CBlock> new_block;
91 : 1 : CBlockIndex* new_block_index = nullptr;
92 : 1 : {
93 [ + - + - : 1 : const CScript script_pub_key{CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG};
+ - ]
94 [ + - ]: 1 : const CBlock block = this->CreateBlock({}, script_pub_key, chainstate);
95 : :
96 [ + - - + ]: 1 : new_block = std::make_shared<CBlock>(block);
97 : :
98 [ + - ]: 1 : LOCK(cs_main);
99 [ + - ]: 1 : BlockValidationState state;
100 [ + - + - : 2 : BOOST_CHECK(CheckBlock(block, state, params.GetConsensus()));
+ - + - ]
101 [ + - + - : 2 : BOOST_CHECK(m_node.chainman->AcceptBlock(new_block, state, &new_block_index, true, nullptr, nullptr, true));
+ - + - ]
102 [ + - + - ]: 1 : CCoinsViewCache view(&chainstate.CoinsTip());
103 [ + - + - : 2 : BOOST_CHECK(chainstate.ConnectBlock(block, state, new_block_index, view));
+ - ]
104 [ + - ]: 3 : }
105 : : // Send block connected notification, then stop the index without
106 : : // sending a chainstate flushed notification. Prior to #24138, this
107 : : // would cause the index to be corrupted and fail to reload.
108 [ + - ]: 1 : ValidationInterfaceTest::BlockConnected(ChainstateRole::NORMAL, index, new_block, new_block_index);
109 [ + - ]: 1 : index.Stop();
110 : 1 : }
111 : :
112 : 1 : {
113 [ + - ]: 1 : CoinStatsIndex index{interfaces::MakeChain(m_node), 1 << 20};
114 [ + - + - : 2 : BOOST_REQUIRE(index.Init());
+ - + - ]
115 : : // Make sure the index can be loaded.
116 [ + - + - : 2 : BOOST_REQUIRE(index.StartBackgroundSync());
+ - + - ]
117 [ + - ]: 1 : index.Stop();
118 : 1 : }
119 : 1 : }
120 : :
121 : : BOOST_AUTO_TEST_SUITE_END()
|