Bitcoin Core  24.1.0
P2P Digital Currency
validation_chainstate_tests.cpp
Go to the documentation of this file.
1 // Copyright (c) 2020-2021 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 <consensus/validation.h>
7 #include <random.h>
8 #include <rpc/blockchain.h>
9 #include <sync.h>
10 #include <test/util/chainstate.h>
11 #include <test/util/setup_common.h>
12 #include <uint256.h>
13 #include <validation.h>
14 
15 #include <vector>
16 
17 #include <boost/test/unit_test.hpp>
18 
19 BOOST_FIXTURE_TEST_SUITE(validation_chainstate_tests, ChainTestingSetup)
20 
21 BOOST_AUTO_TEST_CASE(validation_chainstate_resize_caches)
24 {
26  CTxMemPool& mempool = *Assert(m_node.mempool);
27 
29  auto add_coin = [](CCoinsViewCache& coins_view) -> COutPoint {
30  Coin newcoin;
31  uint256 txid = InsecureRand256();
32  COutPoint outp{txid, 0};
33  newcoin.nHeight = 1;
34  newcoin.out.nValue = InsecureRand32();
35  newcoin.out.scriptPubKey.assign((uint32_t)56, 1);
36  coins_view.AddCoin(outp, std::move(newcoin), false);
37 
38  return outp;
39  };
40 
41  Chainstate& c1 = WITH_LOCK(cs_main, return manager.InitializeChainstate(&mempool));
42  c1.InitCoinsDB(
43  /*cache_size_bytes=*/1 << 23, /*in_memory=*/true, /*should_wipe=*/false);
44  WITH_LOCK(::cs_main, c1.InitCoinsCache(1 << 23));
45  BOOST_REQUIRE(c1.LoadGenesisBlock()); // Need at least one block loaded to be able to flush caches
46 
47  // Add a coin to the in-memory cache, upsize once, then downsize.
48  {
49  LOCK(::cs_main);
50  auto outpoint = add_coin(c1.CoinsTip());
51 
52  // Set a meaningless bestblock value in the coinsview cache - otherwise we won't
53  // flush during ResizecoinsCaches() and will subsequently hit an assertion.
55 
56  BOOST_CHECK(c1.CoinsTip().HaveCoinInCache(outpoint));
57 
58  c1.ResizeCoinsCaches(
59  1 << 24, // upsizing the coinsview cache
60  1 << 22 // downsizing the coinsdb cache
61  );
62 
63  // View should still have the coin cached, since we haven't destructed the cache on upsize.
64  BOOST_CHECK(c1.CoinsTip().HaveCoinInCache(outpoint));
65 
66  c1.ResizeCoinsCaches(
67  1 << 22, // downsizing the coinsview cache
68  1 << 23 // upsizing the coinsdb cache
69  );
70 
71  // The view cache should be empty since we had to destruct to downsize.
72  BOOST_CHECK(!c1.CoinsTip().HaveCoinInCache(outpoint));
73  }
74 }
75 
81 {
83  uint256 curr_tip = ::g_best_block;
84 
85  // Mine 10 more blocks, putting at us height 110 where a valid assumeutxo value can
86  // be found.
87  mineBlocks(10);
88 
89  // After adding some blocks to the tip, best block should have changed.
90  BOOST_CHECK(::g_best_block != curr_tip);
91 
92  BOOST_REQUIRE(CreateAndActivateUTXOSnapshot(m_node, m_path_root));
93 
94  // Ensure our active chain is the snapshot chainstate.
95  BOOST_CHECK(WITH_LOCK(::cs_main, return chainman.IsSnapshotActive()));
96 
97  curr_tip = ::g_best_block;
98 
99  // Mine a new block on top of the activated snapshot chainstate.
100  mineBlocks(1); // Defined in TestChain100Setup.
101 
102  // After adding some blocks to the snapshot tip, best block should have changed.
103  BOOST_CHECK(::g_best_block != curr_tip);
104 
105  curr_tip = ::g_best_block;
106 
107  BOOST_CHECK_EQUAL(chainman.GetAll().size(), 2);
108 
109  Chainstate& background_cs{*[&] {
110  for (Chainstate* cs : chainman.GetAll()) {
111  if (cs != &chainman.ActiveChainstate()) {
112  return cs;
113  }
114  }
115  assert(false);
116  }()};
117 
118  // Create a block to append to the validation chain.
119  std::vector<CMutableTransaction> noTxns;
120  CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
121  CBlock validation_block = this->CreateBlock(noTxns, scriptPubKey, background_cs);
122  auto pblock = std::make_shared<const CBlock>(validation_block);
123  BlockValidationState state;
124  CBlockIndex* pindex = nullptr;
125  const CChainParams& chainparams = Params();
126  bool newblock = false;
127 
128  // TODO: much of this is inlined from ProcessNewBlock(); just reuse PNB()
129  // once it is changed to support multiple chainstates.
130  {
131  LOCK(::cs_main);
132  bool checked = CheckBlock(*pblock, state, chainparams.GetConsensus());
133  BOOST_CHECK(checked);
134  bool accepted = background_cs.AcceptBlock(
135  pblock, state, &pindex, true, nullptr, &newblock, true);
136  BOOST_CHECK(accepted);
137  }
138  // UpdateTip is called here
139  bool block_added = background_cs.ActivateBestChain(state, pblock);
140 
141  // Ensure tip is as expected
142  BOOST_CHECK_EQUAL(background_cs.m_chain.Tip()->GetBlockHash(), validation_block.GetHash());
143 
144  // g_best_block should be unchanged after adding a block to the background
145  // validation chain.
146  BOOST_CHECK(block_added);
147  BOOST_CHECK_EQUAL(curr_tip, ::g_best_block);
148 }
149 
CCoinsViewCache & CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(
Definition: validation.h:541
CAmount nValue
Definition: transaction.h:159
Testing setup that performs all steps up until right before ChainstateManager gets initialized...
Definition: setup_common.h:100
void assign(size_type n, const T &val)
Definition: prevector.h:220
assert(!tx.IsCoinBase())
bool LoadGenesisBlock()
Ensures we have a genesis block in the block tree, possibly writing one to disk.
CScript scriptPubKey
Definition: transaction.h:160
BOOST_FIXTURE_TEST_CASE(chainstate_update_tip, TestChain100Setup)
Test UpdateTip behavior for both active and background chainstates.
A UTXO entry.
Definition: coins.h:30
Definition: block.h:68
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
Definition: validation.h:799
node::NodeContext m_node
Definition: bitcoin-gui.cpp:37
static void pool cs
CTxOut out
unspent transaction output
Definition: coins.h:34
void InitCoinsDB(size_t cache_size_bytes, bool in_memory, bool should_wipe, fs::path leveldb_name="chainstate")
Initialize the CoinsViews UTXO set database management data structures.
bool HaveCoinInCache(const COutPoint &outpoint) const
Check if we have the given utxo already loaded in this cache.
Definition: coins.cpp:164
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system...
Definition: chainparams.h:69
static uint32_t InsecureRand32()
Definition: setup_common.h:72
BOOST_AUTO_TEST_CASE(validation_chainstate_resize_caches)
Test resizing coins-related Chainstate caches during runtime.
uint256 g_best_block
Used to notify getblocktemplate RPC of new tips.
Definition: validation.cpp:125
std::unique_ptr< CTxMemPool > mempool
Definition: context.h:50
void SetBestBlock(const uint256 &hashBlock)
Definition: coins.cpp:175
uint32_t nHeight
at which height this containing transaction was included in the active block chain ...
Definition: coins.h:40
bool IsSnapshotActive() const
Chainstate stores and provides an API to update our local knowledge of the current best chain...
Definition: validation.h:437
#define LOCK(cs)
Definition: sync.h:261
BOOST_AUTO_TEST_SUITE_END()
bool CheckBlock(const CBlock &block, BlockValidationState &state, const Consensus::Params &consensusParams, bool fCheckPOW, bool fCheckMerkleRoot)
Functions for validating blocks and updating the block tree.
Testing fixture that pre-creates a 100-block REGTEST-mode block chain.
Definition: setup_common.h:126
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:34
static void add_coin(const CAmount &nValue, int nInput, std::vector< OutputGroup > &set)
Chainstate &InitializeChainstate(CTxMemPool *mempool, const std::optional< uint256 > &snapshot_blockhash=std::nullopt) LIFETIMEBOUND EXCLUSIVE_LOCKS_REQUIRED(std::vector< Chainstate * GetAll)()
Instantiate a new chainstate and assign it based upon whether it is from a snapshot.
Definition: validation.h:945
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:305
std::vector< unsigned char > ToByteVector(const T &in)
Definition: script.h:63
256-bit opaque blob.
Definition: uint256.h:119
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:431
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:17
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:151
const CChainParams & Params()
Return the currently selected parameters.
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:410
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
Definition: validation.cpp:121
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:82
Chainstate & ActiveChainstate() const
The most-work chain.
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Definition: coins.h:212
static uint256 InsecureRand256()
Definition: setup_common.h:73
std::unique_ptr< ChainstateManager > chainman
Definition: context.h:54
#define Assert(val)
Identity function.
Definition: check.h:74
static bool CreateAndActivateUTXOSnapshot(node::NodeContext &node, const fs::path root, F malleation=NoMalleation)
Create and activate a UTXO snapshot, optionally providing a function to malleate the snapshot...
Definition: chainstate.h:26
#define BOOST_CHECK(expr)
Definition: object.cpp:16