Branch data Line data Source code
1 : : // Copyright (c) 2020-present 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 <index/coinstatsindex.h>
6 : : #include <interfaces/chain.h>
7 : : #include <script/script.h>
8 : : #include <test/util/setup_common.h>
9 : : #include <util/byte_units.h>
10 : : #include <util/check.h>
11 : : #include <validation.h>
12 : :
13 : : #include <boost/test/unit_test.hpp>
14 : :
15 : : // Tests of generic BaseIndex functionality that is independent of which
16 : : // concrete index is being used. CoinStatsIndex is used here merely as a
17 : : // convenient instantiation of BaseIndex.
18 : : BOOST_AUTO_TEST_SUITE(baseindex_tests)
19 : :
20 : : // Test that the index does not commit ahead of the chainstate's last
21 : : // flushed block. If it did, a subsequent unclean shutdown would corrupt
22 : : // the index, because during reverting it would require blocks that were
23 : : // never flushed to disk.
24 [ + - + - : 7 : BOOST_FIXTURE_TEST_CASE(baseindex_no_commit_ahead_of_flush, TestChain100Setup)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
25 : : {
26 [ - + ]: 1 : Chainstate& chainstate = Assert(m_node.chainman)->ActiveChainstate();
27 : 4 : auto sync_index = [&](bool do_flush, int expected_sync_height, int expected_commit_height) {
28 [ + - ]: 3 : CoinStatsIndex index{interfaces::MakeChain(m_node), /*n_cache_size=*/1_MiB};
29 [ + - + - : 6 : BOOST_REQUIRE(index.Init());
+ - + - ]
30 [ + - ]: 3 : index.Sync();
31 [ + + ]: 3 : if (do_flush) {
32 [ + - ]: 1 : chainstate.ForceFlushStateToDisk();
33 [ + - + - ]: 1 : m_node.chain->context()->validation_signals->SyncWithValidationInterfaceQueue();
34 : : }
35 [ + - + - : 3 : BOOST_CHECK_EQUAL(index.GetSummary().best_block_height, expected_sync_height);
+ - ]
36 [ + - ]: 3 : index.Stop();
37 : : // Reload index to see which block data was actually committed.
38 [ + - + - : 6 : BOOST_REQUIRE(index.Init());
+ - + - ]
39 [ + - + - : 3 : BOOST_CHECK_EQUAL(index.GetSummary().best_block_height, expected_commit_height);
+ - ]
40 [ + - ]: 3 : index.Stop();
41 : 4 : };
42 : :
43 : : // Part 1: Sync, then "crash" (stop without flushing). Models a node that
44 : : // started up, had its index catch up, but never flushed before going down.
45 : : // The end-of-sync Commit() runs at chain tip (height 100) but
46 : : // m_last_flushed_block is null, so it is skipped.
47 : 1 : sync_index(false, 100, 0);
48 : :
49 : : // Part 2: Restart cleanly. Sync, force a chainstate flush, and drain the
50 : : // validation queue so the index's ChainStateFlushed callback runs.
51 : : // Now m_last_flushed_block == tip == 100 and the index can commit.
52 : 1 : sync_index(true, 100, 100);
53 : :
54 : : // Part 3: Connect a new block on the chain without flushing
55 : : // (m_last_flushed_block stays at 100). For a real node this would happen
56 : : // in parallel with Sync(). Here we do it before Sync() to make the race
57 : : // state deterministic.
58 [ + - + - ]: 2 : CreateAndProcessBlock({}, CScript() << OP_TRUE);
59 : 1 : sync_index(false, 101, 100);
60 : 1 : }
61 : :
62 : : BOOST_AUTO_TEST_SUITE_END()
|