5 #include <chainparams.h> 26 #include <boost/test/unit_test.hpp> 32 BOOST_FIXTURE_TEST_SUITE(validation_chainstatemanager_tests,
TestingSetup)
40 std::vector<Chainstate*> chainstates;
47 chainstates.push_back(&c1);
51 auto all = manager.
GetAll();
52 BOOST_CHECK_EQUAL_COLLECTIONS(all.begin(), all.end(), chainstates.begin(), chainstates.end());
61 auto exp_tip = c1.m_chain.Tip();
68 const uint256 snapshot_blockhash = active_tip->GetBlockHash();
70 chainstates.push_back(&c2);
72 1 << 23,
true,
false);
75 c2.InitCoinsCache(1 << 23);
88 auto all2 = manager.
GetAll();
89 BOOST_CHECK_EQUAL_COLLECTIONS(all2.begin(), all2.end(), chainstates.begin(), chainstates.end());
113 size_t max_cache = 10000;
117 std::vector<Chainstate*> chainstates;
122 chainstates.push_back(&c1);
125 c1.InitCoinsCache(1 << 23);
126 manager.MaybeRebalanceCaches();
136 chainstates.push_back(&c2);
138 1 << 23,
true,
false);
151 c2.InitCoinsCache(1 << 23);
152 manager.MaybeRebalanceCaches();
190 size_t initial_total_coins{100};
197 size_t total_coins{0};
218 constexpr
int snapshot_height = 110;
221 initial_total_coins += 10;
232 auto_infile >> outpoint;
297 int chains_tested{0};
300 BOOST_TEST_MESSAGE(
"Checking coins in " << chainstate->ToString());
306 size_t total_coins{0};
323 constexpr
size_t new_coins{100};
328 size_t coins_in_active{0};
329 size_t coins_in_background{0};
330 size_t coins_missing_from_background{0};
333 BOOST_TEST_MESSAGE(
"Checking coins in " << chainstate->ToString());
339 if (coinscache.HaveCoin(op)) {
340 (is_background ? coins_in_background : coins_in_active)++;
341 }
else if (is_background) {
342 coins_missing_from_background++;
358 loaded_snapshot_blockhash);
359 return std::make_tuple(&validation_chainstate, &snapshot_chainstate);
370 BOOST_TEST_MESSAGE(
"Simulating node restart");
374 cs->ForceFlushStateToDisk();
379 chainman.ResetChainstates();
387 const BlockManager::Options blockman_opts{
388 .chainparams = chainman_opts.chainparams,
390 .notifications = chainman_opts.notifications,
404 this->SetupSnapshot();
423 int num_assumed_valid{0};
426 const int expected_assumed_valid{20};
427 const int last_assumed_valid_idx{111};
428 const int assumed_valid_start_idx = last_assumed_valid_idx - expected_assumed_valid;
439 auto reload_all_block_indexes = [&]() {
446 cs->ClearBlockIndexCandidates();
455 reload_all_block_indexes();
464 if (i < last_assumed_valid_idx && i >= assumed_valid_start_idx) {
469 if (index->IsAssumedValid()) ++num_assumed_valid;
472 if (i == (assumed_valid_start_idx - 1)) {
473 validated_tip = index;
477 if (i == last_assumed_valid_idx - 1) {
478 assumed_base = index;
480 }
else if (i == last_assumed_valid_idx) {
489 return chainman.ActivateExistingSnapshot(*assumed_base->phashBlock));
505 reload_all_block_indexes();
562 this->SetupSnapshot();
572 auto all_chainstates = chainman.
GetAll();
594 BOOST_TEST_MESSAGE(
"Performing Load/Verify/Activate of chainstate");
597 this->LoadVerifyActivateChainstate();
600 LOCK(chainman_restarted.GetMutex());
602 BOOST_CHECK(chainman_restarted.IsSnapshotActive());
603 BOOST_CHECK(!chainman_restarted.IsSnapshotValidated());
605 BOOST_CHECK_EQUAL(chainman_restarted.ActiveTip()->GetBlockHash(), snapshot_tip_hash);
610 "Ensure we can mine blocks on top of the initialized snapshot chainstate");
613 LOCK(chainman_restarted.GetMutex());
619 if (
cs != &chainman_restarted.ActiveChainstate()) {
628 this->SetupSnapshot();
646 res =
WITH_LOCK(::
cs_main,
return chainman.MaybeCompleteSnapshotValidation());
657 auto all_chainstates = chainman.
GetAll();
662 res =
WITH_LOCK(::
cs_main,
return chainman.MaybeCompleteSnapshotValidation());
676 BOOST_TEST_MESSAGE(
"Performing Load/Verify/Activate of chainstate");
680 this->LoadVerifyActivateChainstate();
701 "Ensure we can mine blocks on top of the \"new\" IBD chainstate");
711 auto chainstates = this->SetupSnapshot();
712 Chainstate& validation_chainstate = *std::get<0>(chainstates);
720 return validation_chainstate.
CoinsTip());
733 res =
WITH_LOCK(::
cs_main,
return chainman.MaybeCompleteSnapshotValidation());
737 auto all_chainstates = chainman.GetAll();
750 BOOST_TEST_MESSAGE(
"Performing Load/Verify/Activate of chainstate");
754 this->LoadVerifyActivateChainstate();
768 "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.
util::SignalInterrupt * shutdown
Interrupt object used to track whether node shutdown was requested.
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.
static const unsigned int MAX_DISCONNECTED_TX_POOL_BYTES
Maximum bytes for transactions to store for processing during reorg.
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. ...
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.
fs::path GetDataDirNet() const
Get data directory path with appended network identifier.
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.
fs::path GetBlocksDirPath() const
Get blocks directory path.
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 transaction_identifier FromUint256(const uint256 &id)
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())
bool IsAssumedValid() const EXCLUSIVE_LOCKS_REQUIRED(
static uint64_t InsecureRandBits(int bits)
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.
#define BOOST_CHECK(expr)
bool HaveCoin(const COutPoint &outpoint) const override
Just check whether a given outpoint is unspent.