5 #include <chainparams.h> 27 #include <boost/test/unit_test.hpp> 33 BOOST_FIXTURE_TEST_SUITE(validation_chainstatemanager_tests,
TestingSetup)
41 std::vector<Chainstate*> chainstates;
48 chainstates.push_back(&c1);
52 auto all = manager.
GetAll();
53 BOOST_CHECK_EQUAL_COLLECTIONS(all.begin(), all.end(), chainstates.begin(), chainstates.end());
62 auto exp_tip = c1.m_chain.Tip();
69 const uint256 snapshot_blockhash = active_tip->GetBlockHash();
71 chainstates.push_back(&c2);
73 1 << 23,
true,
false);
76 c2.InitCoinsCache(1 << 23);
89 auto all2 = manager.
GetAll();
90 BOOST_CHECK_EQUAL_COLLECTIONS(all2.begin(), all2.end(), chainstates.begin(), chainstates.end());
114 size_t max_cache = 10000;
118 std::vector<Chainstate*> chainstates;
123 chainstates.push_back(&c1);
126 c1.InitCoinsCache(1 << 23);
127 manager.MaybeRebalanceCaches();
137 chainstates.push_back(&c2);
139 1 << 23,
true,
false);
152 c2.InitCoinsCache(1 << 23);
153 manager.MaybeRebalanceCaches();
191 size_t initial_total_coins{100};
198 size_t total_coins{0};
219 constexpr
int snapshot_height = 110;
222 initial_total_coins += 10;
233 auto_infile >> outpoint;
298 int chains_tested{0};
301 BOOST_TEST_MESSAGE(
"Checking coins in " << chainstate->ToString());
307 size_t total_coins{0};
324 constexpr
size_t new_coins{100};
329 size_t coins_in_active{0};
330 size_t coins_in_background{0};
331 size_t coins_missing_from_background{0};
334 BOOST_TEST_MESSAGE(
"Checking coins in " << chainstate->ToString());
340 if (coinscache.HaveCoin(op)) {
341 (is_background ? coins_in_background : coins_in_active)++;
342 }
else if (is_background) {
343 coins_missing_from_background++;
359 loaded_snapshot_blockhash);
360 return std::make_tuple(&validation_chainstate, &snapshot_chainstate);
371 BOOST_TEST_MESSAGE(
"Simulating node restart");
375 cs->ForceFlushStateToDisk();
380 chainman.ResetChainstates();
389 const BlockManager::Options blockman_opts{
390 .chainparams = chainman_opts.chainparams,
392 .notifications = chainman_opts.notifications,
406 this->SetupSnapshot();
425 int num_assumed_valid{0};
428 const int expected_assumed_valid{20};
429 const int last_assumed_valid_idx{111};
430 const int assumed_valid_start_idx = last_assumed_valid_idx - expected_assumed_valid;
441 auto reload_all_block_indexes = [&]() {
448 cs->ClearBlockIndexCandidates();
457 reload_all_block_indexes();
466 if (i < last_assumed_valid_idx && i >= assumed_valid_start_idx) {
471 if (index->IsAssumedValid()) ++num_assumed_valid;
474 if (i == (assumed_valid_start_idx - 1)) {
475 validated_tip = index;
479 if (i == last_assumed_valid_idx - 1) {
480 assumed_base = index;
482 }
else if (i == last_assumed_valid_idx) {
491 return chainman.ActivateExistingSnapshot(*assumed_base->phashBlock));
507 reload_all_block_indexes();
564 this->SetupSnapshot();
574 auto all_chainstates = chainman.
GetAll();
596 BOOST_TEST_MESSAGE(
"Performing Load/Verify/Activate of chainstate");
599 this->LoadVerifyActivateChainstate();
602 LOCK(chainman_restarted.GetMutex());
604 BOOST_CHECK(chainman_restarted.IsSnapshotActive());
605 BOOST_CHECK(!chainman_restarted.IsSnapshotValidated());
607 BOOST_CHECK_EQUAL(chainman_restarted.ActiveTip()->GetBlockHash(), snapshot_tip_hash);
612 "Ensure we can mine blocks on top of the initialized snapshot chainstate");
615 LOCK(chainman_restarted.GetMutex());
621 if (
cs != &chainman_restarted.ActiveChainstate()) {
630 this->SetupSnapshot();
648 res =
WITH_LOCK(::
cs_main,
return chainman.MaybeCompleteSnapshotValidation());
659 auto all_chainstates = chainman.
GetAll();
664 res =
WITH_LOCK(::
cs_main,
return chainman.MaybeCompleteSnapshotValidation());
678 BOOST_TEST_MESSAGE(
"Performing Load/Verify/Activate of chainstate");
682 this->LoadVerifyActivateChainstate();
703 "Ensure we can mine blocks on top of the \"new\" IBD chainstate");
713 auto chainstates = this->SetupSnapshot();
714 Chainstate& validation_chainstate = *std::get<0>(chainstates);
722 return validation_chainstate.
CoinsTip());
735 res =
WITH_LOCK(::
cs_main,
return chainman.MaybeCompleteSnapshotValidation());
739 auto all_chainstates = chainman.GetAll();
752 BOOST_TEST_MESSAGE(
"Performing Load/Verify/Activate of chainstate");
756 this->LoadVerifyActivateChainstate();
770 "Ensure we can mine blocks on top of the \"new\" IBD chainstate");
std::shared_ptr< const CTransaction > CTransactionRef
CCoinsViewCache & CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
void SyncWithValidationInterfaceQueue()
This is a synonym for the following, which asserts certain locks are not held: std::promise<void> pro...
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
std::optional< uint256 > ReadSnapshotBaseBlockhash(fs::path chaindir)
size_t m_coinsdb_cache_size_bytes
The cache size of the on-disk coins view.
ChainstateManager & SimulateNodeRestart()
std::atomic< int > exit_status
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
All parent headers found, difficulty matches, timestamp >= median previous, checkpoint.
std::tuple< Chainstate *, Chainstate * > SetupSnapshot()
int Height() const
Return the maximal height in the chain.
CTxOut out
unspent transaction output
const CChainParams & chainparams
std::vector< CTransactionRef > m_coinbase_txns
An options struct for ChainstateManager, more ergonomically referred to as ChainstateManager::Options...
CBlockIndex * Genesis() const
Returns the index entry for the genesis block of this chain, or nullptr if none.
std::optional< fs::path > FindSnapshotChainstateDir(const fs::path &data_dir)
Return a path to the snapshot-based chainstate dir, if one exists.
CChain m_chain
The current chain of blockheaders we consult and build on.
Non-refcounted RAII wrapper for FILE*.
void SetTip(CBlockIndex &block)
Set/initialize a chain with a given tip.
unsigned int nChainTx
(memory only) Number of transactions in the chain up to and including this block. ...
NodeClock::time_point GetAdjustedTime()
void SetBestBlock(const uint256 &hashBlock)
uint256 GetBlockHash() const
unsigned int GetCacheSize() const
Calculate the size of the cache (in number of transaction outputs)
bool DisconnectTip(BlockValidationState &state, DisconnectedBlockTransactions *disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main
Disconnect m_chain's tip.
bool IsSnapshotActive() const
Chainstate stores and provides an API to update our local knowledge of the current best chain...
BOOST_FIXTURE_TEST_CASE(chainstatemanager, TestChain100Setup)
Basic tests for ChainstateManager.
bilingual_str _(const char *psz)
Translation function.
bool LoadBlockIndex() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Load the block tree and coins database from disk, initializing state if we're running with -reindex...
BOOST_AUTO_TEST_SUITE_END()
static const uint256 ZERO
void mineBlocks(int num_blocks)
Mine a series of new blocks on the active chain.
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Maintains a tree of blocks (stored in m_block_index) which is consulted to determine where the most-w...
bool LoadChainTip() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Update the chain tip based on database information, i.e.
RecursiveMutex & GetMutex() const LOCK_RETURNED(
Alias for cs_main.
Testing fixture that pre-creates a 100-block REGTEST-mode block chain.
#define ASSERT_DEBUG_LOG(message)
static uint256 InsecureRand256()
An outpoint - a combination of a transaction hash and an index n into its vout.
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
DisconnectedBlockTransactions.
Chainstate &InitializeChainstate(CTxMemPool *mempool) EXCLUSIVE_LOCKS_REQUIRED(std::vector< Chainstate * GetAll)()
Instantiate a new chainstate.
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
void AddCoin(const COutPoint &outpoint, Coin &&coin, bool possible_overwrite)
Add a coin.
int64_t m_total_coinstip_cache
The total number of bytes available for us to use across all in-memory coins caches.
const CBlockIndex *SnapshotBase() EXCLUSIVE_LOCKS_REQUIRED(std::set< CBlockIndex *, node::CBlockIndexWorkComparator > setBlockIndexCandidates
The base of the snapshot this chainstate was created from.
#define BOOST_CHECK_EQUAL(v1, v2)
The block chain is a tree shaped structure starting with the genesis block at the root...
const CChainParams & Params()
Return the currently selected parameters.
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...
std::unique_ptr< KernelNotifications > notifications
static uint32_t InsecureRand32()
void ResetBlockSequenceCounters() EXCLUSIVE_LOCKS_REQUIRED(
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
int ActiveHeight() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
std::unique_ptr< kernel::Context > kernel
libbitcoin_kernel context
bool IsAssumedValid() const EXCLUSIVE_LOCKS_REQUIRED(
static uint64_t InsecureRandBits(int bits)
const fs::path & GetBlocksDirPath() const
Get blocks directory path.
size_t m_coinstip_cache_size_bytes
The cache size of the in-memory coins view.
std::optional< uint256 > SnapshotBlockhash() const
int64_t m_total_coinsdb_cache
The total number of bytes available for us to use across all leveldb coins databases.
CCoinsView that adds a memory cache for transactions to another CCoinsView.
static bool exists(const path &p)
std::optional< AssumeutxoData > AssumeutxoForHeight(int height) const
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
If ASSUMED_VALID is set, it means that this block has not been validated and has validity status less...
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
SnapshotCompletionResult MaybeCompleteSnapshotValidation() EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex *GetSnapshotBaseBlock() const EXCLUSIVE_LOCKS_REQUIRED(Chainstate ActiveChainstate)() const
Once the background validation chainstate has reached the height which is the base of the UTXO snapsh...
std::unique_ptr< ChainstateManager > chainman
Testing setup that configures a complete environment.
bool IsSnapshotValidated() const EXCLUSIVE_LOCKS_REQUIRED(
Is there a snapshot in use and has it been fully validated?
#define Assert(val)
Identity function.
const fs::path & GetDataDirNet() const
Get data directory path with appended network identifier.
static const unsigned int MAX_DISCONNECTED_TX_POOL_SIZE
Maximum kilobytes for transactions to store for processing during reorg.
#define BOOST_CHECK(expr)
bool HaveCoin(const COutPoint &outpoint) const override
Just check whether a given outpoint is unspent.