Bitcoin Core  25.99.0
P2P Digital Currency
blockmanager_tests.cpp
Go to the documentation of this file.
1 // Copyright (c) 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 <node/blockstorage.h>
7 #include <node/context.h>
8 #include <util/chaintype.h>
9 #include <validation.h>
10 
11 #include <boost/test/unit_test.hpp>
12 #include <test/util/setup_common.h>
13 
14 using node::BlockManager;
17 
18 // use BasicTestingSetup here for the data directory configuration, setup, and cleanup
19 BOOST_FIXTURE_TEST_SUITE(blockmanager_tests, BasicTestingSetup)
20 
21 BOOST_AUTO_TEST_CASE(blockmanager_find_block_pos)
22 {
23  const auto params {CreateChainParams(ArgsManager{}, ChainType::MAIN)};
24  const BlockManager::Options blockman_opts{
25  .chainparams = *params,
26  .blocks_dir = m_args.GetBlocksDirPath(),
27  };
28  BlockManager blockman{blockman_opts};
29  CChain chain {};
30  // simulate adding a genesis block normally
31  BOOST_CHECK_EQUAL(blockman.SaveBlockToDisk(params->GenesisBlock(), 0, chain, nullptr).nPos, BLOCK_SERIALIZATION_HEADER_SIZE);
32  // simulate what happens during reindex
33  // simulate a well-formed genesis block being found at offset 8 in the blk00000.dat file
34  // the block is found at offset 8 because there is an 8 byte serialization header
35  // consisting of 4 magic bytes + 4 length bytes before each block in a well-formed blk file.
37  BOOST_CHECK_EQUAL(blockman.SaveBlockToDisk(params->GenesisBlock(), 0, chain, &pos).nPos, BLOCK_SERIALIZATION_HEADER_SIZE);
38  // now simulate what happens after reindex for the first new block processed
39  // the actual block contents don't matter, just that it's a block.
40  // verify that the write position is at offset 0x12d.
41  // this is a check to make sure that https://github.com/bitcoin/bitcoin/issues/21379 does not recur
42  // 8 bytes (for serialization header) + 285 (for serialized genesis block) = 293
43  // add another 8 bytes for the second block's serialization header and we get 293 + 8 = 301
44  FlatFilePos actual{blockman.SaveBlockToDisk(params->GenesisBlock(), 1, chain, nullptr)};
46 }
47 
48 BOOST_FIXTURE_TEST_CASE(blockmanager_scan_unlink_already_pruned_files, TestChain100Setup)
49 {
50  // Cap last block file size, and mine new block in a new block file.
51  const auto& chainman = Assert(m_node.chainman);
52  auto& blockman = chainman->m_blockman;
53  const CBlockIndex* old_tip{WITH_LOCK(chainman->GetMutex(), return chainman->ActiveChain().Tip())};
54  WITH_LOCK(chainman->GetMutex(), blockman.GetBlockFileInfo(old_tip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE);
55  CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
56 
57  // Prune the older block file, but don't unlink it
58  int file_number;
59  {
60  LOCK(chainman->GetMutex());
61  file_number = old_tip->GetBlockPos().nFile;
62  blockman.PruneOneBlockFile(file_number);
63  }
64 
65  const FlatFilePos pos(file_number, 0);
66 
67  // Check that the file is not unlinked after ScanAndUnlinkAlreadyPrunedFiles
68  // if m_have_pruned is not yet set
69  WITH_LOCK(chainman->GetMutex(), blockman.ScanAndUnlinkAlreadyPrunedFiles());
70  BOOST_CHECK(!AutoFile(blockman.OpenBlockFile(pos, true)).IsNull());
71 
72  // Check that the file is unlinked after ScanAndUnlinkAlreadyPrunedFiles
73  // once m_have_pruned is set
74  blockman.m_have_pruned = true;
75  WITH_LOCK(chainman->GetMutex(), blockman.ScanAndUnlinkAlreadyPrunedFiles());
76  BOOST_CHECK(AutoFile(blockman.OpenBlockFile(pos, true)).IsNull());
77 
78  // Check that calling with already pruned files doesn't cause an error
79  WITH_LOCK(chainman->GetMutex(), blockman.ScanAndUnlinkAlreadyPrunedFiles());
80 
81  // Check that the new tip file has not been removed
82  const CBlockIndex* new_tip{WITH_LOCK(chainman->GetMutex(), return chainman->ActiveChain().Tip())};
83  BOOST_CHECK_NE(old_tip, new_tip);
84  const int new_file_number{WITH_LOCK(chainman->GetMutex(), return new_tip->GetBlockPos().nFile)};
85  const FlatFilePos new_pos(new_file_number, 0);
86  BOOST_CHECK(!AutoFile(blockman.OpenBlockFile(new_pos, true)).IsNull());
87 }
88 
node::NodeContext m_node
Definition: bitcoin-gui.cpp:37
BOOST_AUTO_TEST_CASE(blockmanager_find_block_pos)
BOOST_FIXTURE_TEST_CASE(blockmanager_scan_unlink_already_pruned_files, TestChain100Setup)
std::unique_ptr< const CChainParams > CreateChainParams(const ArgsManager &args, const ChainType chain)
Creates and returns a std::unique_ptr<CChainParams> of the chosen chain.
#define Assert(val)
Identity function.
Definition: check.h:73
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:488
bool IsNull() const
Return true if the wrapped FILE* is nullptr, false otherwise.
Definition: streams.h:528
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:151
An in-memory indexed chain of blocks.
Definition: chain.h:436
Maintains a tree of blocks (stored in m_block_index) which is consulted to determine where the most-w...
Definition: blockstorage.h:79
static const int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
Definition: clientversion.h:33
BOOST_AUTO_TEST_SUITE_END()
static constexpr size_t BLOCK_SERIALIZATION_HEADER_SIZE
Size of header written by WriteBlockToDisk before a serialized CBlock.
Definition: blockstorage.h:47
static const unsigned int MAX_BLOCKFILE_SIZE
The maximum size of a blk?????.dat file (since 0.8)
Definition: blockstorage.h:44
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
#define BOOST_CHECK(expr)
Definition: object.cpp:17
size_t GetSerializeSize(const T &t, int nVersion=0)
Definition: serialize.h:1109
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Definition: standard.cpp:339
Basic testing setup.
Definition: setup_common.h:80
Testing fixture that pre-creates a 100-block REGTEST-mode block chain.
Definition: setup_common.h:129
std::unique_ptr< ChainstateManager > chainman
Definition: context.h:56
#define LOCK(cs)
Definition: sync.h:258
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:302