Bitcoin Core  31.0.0
P2P Digital Currency
validation_chainstate_tests.cpp
Go to the documentation of this file.
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 <chainparams.h>
6 #include <consensus/amount.h>
7 #include <consensus/validation.h>
9 #include <random.h>
10 #include <rpc/blockchain.h>
11 #include <script/script.h>
12 #include <sync.h>
13 #include <test/util/chainstate.h>
14 #include <test/util/common.h>
15 #include <test/util/coins.h>
16 #include <test/util/random.h>
17 #include <test/util/setup_common.h>
18 #include <uint256.h>
19 #include <util/check.h>
20 #include <validation.h>
21 
22 #include <vector>
23 
24 #include <boost/test/unit_test.hpp>
25 
26 BOOST_FIXTURE_TEST_SUITE(validation_chainstate_tests, ChainTestingSetup)
27 
28 BOOST_AUTO_TEST_CASE(validation_chainstate_resize_caches)
31 {
33  CTxMemPool& mempool = *Assert(m_node.mempool);
34  Chainstate& c1 = WITH_LOCK(cs_main, return manager.InitializeChainstate(&mempool));
35  c1.InitCoinsDB(
36  /*cache_size_bytes=*/1 << 23, /*in_memory=*/true, /*should_wipe=*/false);
37  WITH_LOCK(::cs_main, c1.InitCoinsCache(1 << 23));
38  BOOST_REQUIRE(c1.LoadGenesisBlock()); // Need at least one block loaded to be able to flush caches
39 
40  // Add a coin to the in-memory cache, upsize once, then downsize.
41  {
42  LOCK(::cs_main);
43  const auto outpoint = AddTestCoin(m_rng, c1.CoinsTip());
44 
45  // Set a meaningless bestblock value in the coinsview cache - otherwise we won't
46  // flush during ResizecoinsCaches() and will subsequently hit an assertion.
47  c1.CoinsTip().SetBestBlock(m_rng.rand256());
48 
49  BOOST_CHECK(c1.CoinsTip().HaveCoinInCache(outpoint));
50 
51  c1.ResizeCoinsCaches(
52  1 << 24, // upsizing the coinsview cache
53  1 << 22 // downsizing the coinsdb cache
54  );
55 
56  // View should still have the coin cached, since we haven't destructed the cache on upsize.
57  BOOST_CHECK(c1.CoinsTip().HaveCoinInCache(outpoint));
58 
59  c1.ResizeCoinsCaches(
60  1 << 22, // downsizing the coinsview cache
61  1 << 23 // upsizing the coinsdb cache
62  );
63 
64  // The view cache should be empty since we had to destruct to downsize.
65  BOOST_CHECK(!c1.CoinsTip().HaveCoinInCache(outpoint));
66  }
67 }
68 
69 BOOST_FIXTURE_TEST_CASE(connect_tip_does_not_cache_inputs_on_failed_connect, TestChain100Setup)
70 {
71  Chainstate& chainstate{Assert(m_node.chainman)->ActiveChainstate()};
72 
73  COutPoint outpoint;
74  {
75  LOCK(cs_main);
76  outpoint = AddTestCoin(m_rng, chainstate.CoinsTip());
77  chainstate.CoinsTip().Flush(/*reallocate_cache=*/false);
78  }
79 
81  tx.vin.emplace_back(outpoint);
82  tx.vout.emplace_back(MAX_MONEY, CScript{} << OP_TRUE);
83 
84  const auto tip{WITH_LOCK(cs_main, return chainstate.m_chain.Tip()->GetBlockHash())};
85  const CBlock block{CreateBlock({tx}, CScript{} << OP_TRUE, chainstate)};
86  BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlock(std::make_shared<CBlock>(block), true, true, nullptr));
87 
88  LOCK(cs_main);
89  BOOST_CHECK_EQUAL(tip, chainstate.m_chain.Tip()->GetBlockHash()); // block rejected
90  BOOST_CHECK(!chainstate.CoinsTip().HaveCoinInCache(outpoint)); // input not cached
91 }
92 
98 {
100  const auto get_notify_tip{[&]() {
101  LOCK(m_node.notifications->m_tip_block_mutex);
102  BOOST_REQUIRE(m_node.notifications->TipBlock());
103  return *m_node.notifications->TipBlock();
104  }};
105  uint256 curr_tip = get_notify_tip();
106 
107  // Mine 10 more blocks, putting at us height 110 where a valid assumeutxo value can
108  // be found.
109  mineBlocks(10);
110 
111  // After adding some blocks to the tip, best block should have changed.
112  BOOST_CHECK(get_notify_tip() != curr_tip);
113 
114  // Grab block 1 from disk; we'll add it to the background chain later.
115  std::shared_ptr<CBlock> pblockone = std::make_shared<CBlock>();
116  {
117  LOCK(::cs_main);
118  chainman.m_blockman.ReadBlock(*pblockone, *chainman.ActiveChain()[1]);
119  }
120 
121  BOOST_REQUIRE(CreateAndActivateUTXOSnapshot(
122  this, NoMalleation, /*reset_chainstate=*/ true));
123 
124  // Ensure our active chain is the snapshot chainstate.
126 
127  curr_tip = get_notify_tip();
128 
129  // Mine a new block on top of the activated snapshot chainstate.
130  mineBlocks(1); // Defined in TestChain100Setup.
131 
132  // After adding some blocks to the snapshot tip, best block should have changed.
133  BOOST_CHECK(get_notify_tip() != curr_tip);
134 
135  curr_tip = get_notify_tip();
136 
137  Chainstate& background_cs{*Assert(WITH_LOCK(::cs_main, return chainman.HistoricalChainstate()))};
138 
139  // Append the first block to the background chain.
140  BlockValidationState state;
141  CBlockIndex* pindex = nullptr;
142  const CChainParams& chainparams = Params();
143  bool newblock = false;
144 
145  // TODO: much of this is inlined from ProcessNewBlock(); just reuse PNB()
146  // once it is changed to support multiple chainstates.
147  {
148  LOCK(::cs_main);
149  bool checked = CheckBlock(*pblockone, state, chainparams.GetConsensus());
150  BOOST_CHECK(checked);
151  bool accepted = chainman.AcceptBlock(
152  pblockone, state, &pindex, true, nullptr, &newblock, true);
153  BOOST_CHECK(accepted);
154  }
155 
156  // UpdateTip is called here
157  bool block_added = background_cs.ActivateBestChain(state, pblockone);
158 
159  // Ensure tip is as expected
160  BOOST_CHECK_EQUAL(background_cs.m_chain.Tip()->GetBlockHash(), pblockone->GetHash());
161 
162  // get_notify_tip() should be unchanged after adding a block to the background
163  // validation chain.
164  BOOST_CHECK(block_added);
165  BOOST_CHECK_EQUAL(curr_tip, get_notify_tip());
166 }
167 
CCoinsViewCache & CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(
Definition: validation.h:686
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
Definition: validation.h:1038
const std::optional< uint256 > m_from_snapshot_blockhash
The blockhash which is the base of the snapshot this chainstate was created from. ...
Definition: validation.h:637
Testing setup that performs all steps up until right before ChainstateManager gets initialized...
Definition: setup_common.h:106
bool LoadGenesisBlock()
Ensures we have a genesis block in the block tree, possibly writing one to disk.
Definition: block.h:73
Interface for managing multiple Chainstate objects, where each chainstate is associated with chainsta...
Definition: validation.h:939
node::NodeContext m_node
Definition: bitcoin-gui.cpp:43
std::vector< CTxIn > vin
Definition: transaction.h:359
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Definition: validation.h:1165
bool HaveCoinInCache(const COutPoint &outpoint) const
Check if we have the given utxo already loaded in this cache.
Definition: coins.cpp:193
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system...
Definition: chainparams.h:76
COutPoint AddTestCoin(FastRandomContext &rng, CCoinsViewCache &coins_view)
Create a Coin with DynamicMemoryUsage of 80 bytes and add it to the given view.
Definition: coins.cpp:16
BOOST_AUTO_TEST_CASE(validation_chainstate_resize_caches)
Test resizing coins-related Chainstate caches during runtime.
BOOST_FIXTURE_TEST_CASE(connect_tip_does_not_cache_inputs_on_failed_connect, TestChain100Setup)
std::unique_ptr< CTxMemPool > mempool
Definition: context.h:68
void SetBestBlock(const uint256 &hashBlock)
Definition: coins.cpp:204
Definition: script.h:84
Chainstate stores and provides an API to update our local knowledge of the current best chain...
Definition: validation.h:550
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
#define LOCK(cs)
Definition: sync.h:258
BOOST_AUTO_TEST_SUITE_END()
SnapshotCompletionResult MaybeValidateSnapshot(Chainstate &validated_cs, Chainstate &unvalidated_cs) EXCLUSIVE_LOCKS_REQUIRED(Chainstate & CurrentChainstate() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Try to validate an assumeutxo snapshot by using a validated historical chainstate targeted at the sna...
Definition: validation.h:1119
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:146
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:28
std::vector< CTxOut > vout
Definition: transaction.h:360
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:289
256-bit opaque blob.
Definition: uint256.h:195
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:186
#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:93
const CChainParams & Params()
Return the currently selected parameters.
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:404
static bool CreateAndActivateUTXOSnapshot(TestingSetup *fixture, F malleation=NoMalleation, bool reset_chainstate=false, bool in_memory_chainstate=false)
Create and activate a UTXO snapshot, optionally providing a function to malleate the snapshot...
Definition: chainstate.h:33
std::unique_ptr< KernelNotifications > notifications
Issues blocking calls about sync status, errors and warnings.
Definition: context.h:86
static constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
Definition: amount.h:26
bool ReadBlock(CBlock &block, const FlatFilePos &pos, const std::optional< uint256 > &expected_hash) const
Functions for disk access for blocks.
bool AcceptBlock(const std::shared_ptr< const CBlock > &pblock, BlockValidationState &state, CBlockIndex **ppindex, bool fRequested, const FlatFilePos *dbp, bool *fNewBlock, bool min_pow_checked) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Sufficiently validate a block for disk storage (and store on disk).
A mutable version of CTransaction.
Definition: transaction.h:357
const auto NoMalleation
Definition: chainstate.h:19
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:89
Chainstate * HistoricalChainstate() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Return historical chainstate targeting a specific block, if any.
Definition: validation.h:1128
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
Definition: cs_main.cpp:8
std::unique_ptr< ChainstateManager > chainman
Definition: context.h:72
#define Assert(val)
Identity function.
Definition: check.h:113
#define BOOST_CHECK(expr)
Definition: object.cpp:16