1 // Copyright (c) 2020 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 <random.h>
6 #include <uint256.h>
7 #include <consensus/validation.h>
8 #include <sync.h>
9 #include <test/util/setup_common.h>
10 #include <validation.h>
11 
12 #include <vector>
13 
14 #include <boost/test/unit_test.hpp>
15 
BOOST_FIXTURE_TEST_SUITE(validation_chainstate_tests,TestingSetup)16 BOOST_FIXTURE_TEST_SUITE(validation_chainstate_tests, TestingSetup)
17 
18 //! Test resizing coins-related CChainState caches during runtime.
19 //!
20 BOOST_AUTO_TEST_CASE(validation_chainstate_resize_caches)
21 {
22     ChainstateManager manager;
23     CTxMemPool mempool;
24 
25     //! Create and add a Coin with DynamicMemoryUsage of 80 bytes to the given view.
26     auto add_coin = [](CCoinsViewCache& coins_view) -> COutPoint {
27         Coin newcoin;
28         uint256 txid = InsecureRand256();
29         COutPoint outp{txid, 0};
30         newcoin.nHeight = 1;
31         newcoin.out.nValue = InsecureRand32();
32         newcoin.out.scriptPubKey.assign((uint32_t)56, 1);
33         coins_view.AddCoin(outp, std::move(newcoin), false);
34 
35         return outp;
36     };
37 
38     CChainState& c1 = WITH_LOCK(cs_main, return manager.InitializeChainstate(&mempool));
39     c1.InitCoinsDB(
40         /* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);
41     WITH_LOCK(::cs_main, c1.InitCoinsCache(1 << 23));
42 
43     // Add a coin to the in-memory cache, upsize once, then downsize.
44     {
45         LOCK(::cs_main);
46         auto outpoint = add_coin(c1.CoinsTip());
47 
48         // Set a meaningless bestblock value in the coinsview cache - otherwise we won't
49         // flush during ResizecoinsCaches() and will subsequently hit an assertion.
50         c1.CoinsTip().SetBestBlock(InsecureRand256());
51 
52         BOOST_CHECK(c1.CoinsTip().HaveCoinInCache(outpoint));
53 
54         c1.ResizeCoinsCaches(
55             1 << 24,  // upsizing the coinsview cache
56             1 << 22  // downsizing the coinsdb cache
57         );
58 
59         // View should still have the coin cached, since we haven't destructed the cache on upsize.
60         BOOST_CHECK(c1.CoinsTip().HaveCoinInCache(outpoint));
61 
62         c1.ResizeCoinsCaches(
63             1 << 22,  // downsizing the coinsview cache
64             1 << 23  // upsizing the coinsdb cache
65         );
66 
67         // The view cache should be empty since we had to destruct to downsize.
68         BOOST_CHECK(!c1.CoinsTip().HaveCoinInCache(outpoint));
69     }
70 
71     // Avoid triggering the address sanitizer.
72     WITH_LOCK(::cs_main, manager.Unload());
73 }
74 
75 BOOST_AUTO_TEST_SUITE_END()
76