Bitcoin Core 31.99.0
P2P Digital Currency
chainstate_write_tests.cpp
Go to the documentation of this file.
1// Copyright (c) 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
6#include <test/util/time.h>
7#include <validation.h>
9
10#include <boost/test/unit_test.hpp>
11
13
14// Taken from validation.cpp
15static constexpr auto DATABASE_WRITE_INTERVAL_MIN{50min};
16static constexpr auto DATABASE_WRITE_INTERVAL_MAX{70min};
17
18BOOST_AUTO_TEST_SUITE(chainstate_write_tests)
19
20BOOST_FIXTURE_TEST_CASE(chainstate_write_interval, TestingSetup)
21{
23 bool m_did_flush{false};
24 void ChainStateFlushed(const ChainstateRole&, const CBlockLocator&) override
25 {
26 m_did_flush = true;
27 }
28 };
29
30 const auto sub{std::make_shared<TestSubscriber>()};
31 m_node.validation_signals->RegisterSharedValidationInterface(sub);
32 auto& chainstate{Assert(m_node.chainman)->ActiveChainstate()};
33 BlockValidationState state_dummy{};
34 NodeClockContext clock_ctx{};
35
36 // The first periodic flush sets m_next_write and does not flush
37 chainstate.FlushStateToDisk(state_dummy, FlushStateMode::PERIODIC);
38 m_node.validation_signals->SyncWithValidationInterfaceQueue();
39 BOOST_CHECK(!sub->m_did_flush);
40
41 // The periodic flush interval is between 50 and 70 minutes (inclusive)
42 clock_ctx += DATABASE_WRITE_INTERVAL_MIN - 1min;
43 chainstate.FlushStateToDisk(state_dummy, FlushStateMode::PERIODIC);
44 m_node.validation_signals->SyncWithValidationInterfaceQueue();
45 BOOST_CHECK(!sub->m_did_flush);
46
47 clock_ctx += DATABASE_WRITE_INTERVAL_MAX;
48 chainstate.FlushStateToDisk(state_dummy, FlushStateMode::PERIODIC);
49 m_node.validation_signals->SyncWithValidationInterfaceQueue();
50 BOOST_CHECK(sub->m_did_flush);
51}
52
53// Test that we do PERIODIC flushes inside ActivateBestChain.
54// This is necessary for reindex-chainstate to be able to periodically flush
55// before reaching chain tip.
56BOOST_FIXTURE_TEST_CASE(write_during_multiblock_activation, TestChain100Setup)
57{
59 {
60 const CBlockIndex* m_tip{nullptr};
61 const CBlockIndex* m_flushed_at_block{nullptr};
62 void ChainStateFlushed(const ChainstateRole&, const CBlockLocator&) override
63 {
64 m_flushed_at_block = m_tip;
65 }
66 void UpdatedBlockTip(const CBlockIndex* block_index, const CBlockIndex*, bool) override {
67 m_tip = block_index;
68 }
69 };
70
71 auto& chainstate{Assert(m_node.chainman)->ActiveChainstate()};
72 BlockValidationState state_dummy{};
73
74 // Pop two blocks from the tip
75 const CBlockIndex* tip{chainstate.m_chain.Tip()};
76 CBlockIndex* second_from_tip{tip->pprev};
77
78 {
79 LOCK2(m_node.chainman->GetMutex(), chainstate.MempoolMutex());
80 chainstate.DisconnectTip(state_dummy, nullptr);
81 chainstate.DisconnectTip(state_dummy, nullptr);
82 }
83
84 BOOST_CHECK_EQUAL(second_from_tip->pprev, chainstate.m_chain.Tip());
85
86 // Set m_next_write to current time
87 chainstate.FlushStateToDisk(state_dummy, FlushStateMode::FORCE_FLUSH);
88 m_node.validation_signals->SyncWithValidationInterfaceQueue();
89 // The periodic flush interval is between 50 and 70 minutes (inclusive)
90 // The next call to a PERIODIC write will flush
92
93 const auto sub{std::make_shared<TestSubscriber>()};
94 m_node.validation_signals->RegisterSharedValidationInterface(sub);
95
96 // ActivateBestChain back to tip
97 chainstate.ActivateBestChain(state_dummy, nullptr);
98 BOOST_CHECK_EQUAL(tip, chainstate.m_chain.Tip());
99 // Check that we flushed inside ActivateBestChain while we were at the
100 // second block from tip, since FlushStateToDisk is called with PERIODIC
101 // inside the outer loop.
102 m_node.validation_signals->SyncWithValidationInterfaceQueue();
103 BOOST_CHECK_EQUAL(sub->m_flushed_at_block, second_from_tip);
104}
105
node::NodeContext m_node
Definition: bitcoin-gui.cpp:47
BOOST_FIXTURE_TEST_CASE(chainstate_write_interval, TestingSetup)
static constexpr auto DATABASE_WRITE_INTERVAL_MAX
static constexpr auto DATABASE_WRITE_INTERVAL_MIN
#define Assert(val)
Identity function.
Definition: check.h:116
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:94
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:100
Implement this to subscribe to events generated in validation and mempool.
virtual void ChainStateFlushed(const kernel::ChainstateRole &role, const CBlockLocator &locator)
Notifies listeners of the new active block chain on-disk.
Helper to initialize the global NodeClock, let a duration elapse, and reset it after use in a test.
Definition: time.h:40
BOOST_AUTO_TEST_SUITE_END()
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:17
#define BOOST_CHECK(expr)
Definition: object.cpp:16
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
Definition: block.h:117
Testing fixture that pre-creates a 100-block REGTEST-mode block chain.
Definition: setup_common.h:143
void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override
Notifies listeners when the block chain tip advances.
Testing setup that configures a complete environment.
Definition: setup_common.h:118
Information about chainstate that notifications are sent from.
Definition: types.h:18
std::unique_ptr< ValidationSignals > validation_signals
Issues calls about blocks and transactions.
Definition: context.h:90
std::unique_ptr< ChainstateManager > chainman
Definition: context.h:74
#define LOCK2(cs1, cs2)
Definition: sync.h:269
std::chrono::seconds GetMockTime()
For testing.
Definition: time.cpp:60
void SetMockTime(int64_t nMockTimeIn)
DEPRECATED Use SetMockTime with chrono type.
Definition: time.cpp:52