Bitcoin Core 28.99.0
P2P Digital Currency
coinstatsindex_tests.cpp
Go to the documentation of this file.
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>
7#include <interfaces/chain.h>
8#include <kernel/coinstats.h>
9#include <test/util/index.h>
12#include <validation.h>
13
14#include <boost/test/unit_test.hpp>
15
16BOOST_AUTO_TEST_SUITE(coinstatsindex_tests)
17
18BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
19{
20 CoinStatsIndex coin_stats_index{interfaces::MakeChain(m_node), 1 << 20, true};
21 BOOST_REQUIRE(coin_stats_index.Init());
22
23 const CBlockIndex* block_index;
24 {
26 block_index = m_node.chainman->ActiveChain().Tip();
27 }
28
29 // CoinStatsIndex should not be found before it is started.
30 BOOST_CHECK(!coin_stats_index.LookUpStats(*block_index));
31
32 // BlockUntilSyncedToCurrentChain should return false before CoinStatsIndex
33 // is started.
34 BOOST_CHECK(!coin_stats_index.BlockUntilSyncedToCurrentChain());
35
36 BOOST_REQUIRE(coin_stats_index.StartBackgroundSync());
37
38 IndexWaitSynced(coin_stats_index, *Assert(m_node.shutdown_signal));
39
40 // Check that CoinStatsIndex works for genesis block.
41 const CBlockIndex* genesis_block_index;
42 {
44 genesis_block_index = m_node.chainman->ActiveChain().Genesis();
45 }
46 BOOST_CHECK(coin_stats_index.LookUpStats(*genesis_block_index));
47
48 // Check that CoinStatsIndex updates with new blocks.
49 BOOST_CHECK(coin_stats_index.LookUpStats(*block_index));
50
51 const CScript script_pub_key{CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG};
52 std::vector<CMutableTransaction> noTxns;
53 CreateAndProcessBlock(noTxns, script_pub_key);
54
55 // Let the CoinStatsIndex to catch up again.
56 BOOST_CHECK(coin_stats_index.BlockUntilSyncedToCurrentChain());
57
58 const CBlockIndex* new_block_index;
59 {
61 new_block_index = m_node.chainman->ActiveChain().Tip();
62 }
63 BOOST_CHECK(coin_stats_index.LookUpStats(*new_block_index));
64
65 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 m_node.validation_signals->SyncWithValidationInterfaceQueue();
74
75 // Shutdown sequence (c.f. Shutdown() in init.cpp)
76 coin_stats_index.Stop();
77}
78
79// Test shutdown between BlockConnected and ChainStateFlushed notifications,
80// make sure index is not corrupted and is able to reload.
81BOOST_FIXTURE_TEST_CASE(coinstatsindex_unclean_shutdown, TestChain100Setup)
82{
83 Chainstate& chainstate = Assert(m_node.chainman)->ActiveChainstate();
84 const CChainParams& params = Params();
85 {
87 BOOST_REQUIRE(index.Init());
88 BOOST_REQUIRE(index.StartBackgroundSync());
90 std::shared_ptr<const CBlock> new_block;
91 CBlockIndex* new_block_index = nullptr;
92 {
93 const CScript script_pub_key{CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG};
94 const CBlock block = this->CreateBlock({}, script_pub_key, chainstate);
95
96 new_block = std::make_shared<CBlock>(block);
97
100 BOOST_CHECK(CheckBlock(block, state, params.GetConsensus()));
101 BOOST_CHECK(m_node.chainman->AcceptBlock(new_block, state, &new_block_index, true, nullptr, nullptr, true));
102 CCoinsViewCache view(&chainstate.CoinsTip());
103 BOOST_CHECK(chainstate.ConnectBlock(block, state, new_block_index, view));
104 }
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 ValidationInterfaceTest::BlockConnected(ChainstateRole::NORMAL, index, new_block, new_block_index);
109 index.Stop();
110 }
111
112 {
114 BOOST_REQUIRE(index.Init());
115 // Make sure the index can be loaded.
116 BOOST_REQUIRE(index.StartBackgroundSync());
117 index.Stop();
118 }
119}
120
node::NodeContext m_node
Definition: bitcoin-gui.cpp:42
const CChainParams & Params()
Return the currently selected parameters.
#define Assert(val)
Identity function.
Definition: check.h:85
Definition: block.h:69
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:141
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
Definition: chainparams.h:81
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:93
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Definition: coins.h:363
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:415
Chainstate stores and provides an API to update our local knowledge of the current best chain.
Definition: validation.h:505
CCoinsViewCache & CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(
Definition: validation.h:611
bool ActivateBestChain(BlockValidationState &state, std::shared_ptr< const CBlock > pblock=nullptr) LOCKS_EXCLUDED(DisconnectResult DisconnectBlock(const CBlock &block, const CBlockIndex *pindex, CCoinsViewCache &view) EXCLUSIVE_LOCKS_REQUIRED(boo ConnectBlock)(const CBlock &block, BlockValidationState &state, CBlockIndex *pindex, CCoinsViewCache &view, bool fJustCheck=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Find the best known block, and make it the tip of the block chain.
Definition: validation.h:709
CoinStatsIndex maintains statistics on the UTXO set.
static void BlockConnected(ChainstateRole role, CValidationInterface &obj, const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Definition: validation.cpp:25
BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition: cs_main.cpp:8
BOOST_AUTO_TEST_SUITE_END()
void IndexWaitSynced(const BaseIndex &index, const util::SignalInterrupt &interrupt)
Block until the index is synced to the current chain.
Definition: index.cpp:12
std::unique_ptr< Chain > MakeChain(node::NodeContext &node)
Return implementation of Chain interface.
Definition: interfaces.cpp:999
#define BOOST_CHECK(expr)
Definition: object.cpp:17
@ OP_CHECKSIG
Definition: script.h:190
std::vector< unsigned char > ToByteVector(const T &in)
Definition: script.h:67
Testing fixture that pre-creates a 100-block REGTEST-mode block chain.
Definition: setup_common.h:139
std::unique_ptr< ValidationSignals > validation_signals
Issues calls about blocks and transactions.
Definition: context.h:88
std::unique_ptr< ChainstateManager > chainman
Definition: context.h:72
util::SignalInterrupt * shutdown_signal
Interrupt object used to track whether node shutdown was requested.
Definition: context.h:65
#define LOCK(cs)
Definition: sync.h:257
bool CheckBlock(const CBlock &block, BlockValidationState &state, const Consensus::Params &consensusParams, bool fCheckPOW, bool fCheckMerkleRoot)
Functions for validating blocks and updating the block tree.