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());
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;
294 int chains_tested{0};
297 BOOST_TEST_MESSAGE(
"Checking coins in " << chainstate->ToString());
303 size_t total_coins{0};
320 constexpr
size_t new_coins{100};
321 mineBlocks(new_coins);
325 size_t coins_in_active{0};
326 size_t coins_in_background{0};
327 size_t coins_missing_from_background{0};
330 BOOST_TEST_MESSAGE(
"Checking coins in " << chainstate->ToString());
337 (is_background ? coins_in_background : coins_in_active)++;
338 }
else if (is_background) {
339 coins_missing_from_background++;
355 loaded_snapshot_blockhash);
356 return std::make_tuple(&validation_chainstate, &snapshot_chainstate);
367 BOOST_TEST_MESSAGE(
"Simulating node restart");
371 cs->ForceFlushStateToDisk();
376 chainman.ResetChainstates();
385 const BlockManager::Options blockman_opts{
386 .chainparams = chainman_opts.chainparams,
387 .blocks_dir = m_args.GetBlocksDirPath(),
388 .notifications = chainman_opts.notifications,
402 this->SetupSnapshot();
423 const int expected_assumed_valid{20};
424 const int last_assumed_valid_idx{111};
425 const int assumed_valid_start_idx = last_assumed_valid_idx - expected_assumed_valid;
436 auto reload_all_block_indexes = [&]() {
443 cs->ClearBlockIndexCandidates();
452 reload_all_block_indexes();
461 if (i < last_assumed_valid_idx && i >= assumed_valid_start_idx) {
470 if (i == (assumed_valid_start_idx - 1)) {
471 validated_tip = index;
474 if (i == last_assumed_valid_idx - 1) {
475 assumed_base = index;
481 return chainman.ActivateExistingSnapshot(*assumed_base->phashBlock));
497 reload_all_block_indexes();
554 this->SetupSnapshot();
564 auto all_chainstates = chainman.
GetAll();
586 BOOST_TEST_MESSAGE(
"Performing Load/Verify/Activate of chainstate");
589 this->LoadVerifyActivateChainstate();
602 "Ensure we can mine blocks on top of the initialized snapshot chainstate");
620 this->SetupSnapshot();
638 res =
WITH_LOCK(::
cs_main,
return chainman.MaybeCompleteSnapshotValidation());
649 auto all_chainstates = chainman.
GetAll();
654 res =
WITH_LOCK(::
cs_main,
return chainman.MaybeCompleteSnapshotValidation());
668 BOOST_TEST_MESSAGE(
"Performing Load/Verify/Activate of chainstate");
672 this->LoadVerifyActivateChainstate();
693 "Ensure we can mine blocks on top of the \"new\" IBD chainstate");
703 auto chainstates = this->SetupSnapshot();
704 Chainstate& validation_chainstate = *std::get<0>(chainstates);
712 return validation_chainstate.
CoinsTip());
725 res =
WITH_LOCK(::
cs_main,
return chainman.MaybeCompleteSnapshotValidation());
729 auto all_chainstates = chainman.
GetAll();
742 BOOST_TEST_MESSAGE(
"Performing Load/Verify/Activate of chainstate");
746 this->LoadVerifyActivateChainstate();
760 "Ensure we can mine blocks on top of the \"new\" IBD chainstate");
@ BLOCK_VALID_TREE
All parent headers found, difficulty matches, timestamp >= median previous, checkpoint.
const CChainParams & Params()
Return the currently selected parameters.
#define Assert(val)
Identity function.
fs::path GetDataDirNet() const
Get data directory path with appended network identifier.
Non-refcounted RAII wrapper for FILE*.
The block chain is a tree shaped structure starting with the genesis block at the root,...
uint256 GetBlockHash() const
unsigned int nChainTx
(memory only) Number of transactions in the chain up to and including this block.
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
void SetTip(CBlockIndex &block)
Set/initialize a chain with a given tip.
int Height() const
Return the maximal height in the chain.
std::optional< AssumeutxoData > AssumeutxoForHeight(int height) const
CCoinsView that adds a memory cache for transactions to another CCoinsView.
void AddCoin(const COutPoint &outpoint, Coin &&coin, bool possible_overwrite)
Add a coin.
unsigned int GetCacheSize() const
Calculate the size of the cache (in number of transaction outputs)
void SetBestBlock(const uint256 &hashBlock)
bool HaveCoin(const COutPoint &outpoint) const override
Just check whether a given outpoint is unspent.
An outpoint - a combination of a transaction hash and an index n into its vout.
Chainstate stores and provides an API to update our local knowledge of the current best chain.
const CBlockIndex *SnapshotBase() EXCLUSIVE_LOCKS_REQUIRED(std::set< CBlockIndex *, node::CBlockIndexWorkComparator > setBlockIndexCandidates
The base of the snapshot this chainstate was created from.
CChain m_chain
The current chain of blockheaders we consult and build on.
size_t m_coinstip_cache_size_bytes
The cache size of the in-memory coins view.
bool LoadChainTip() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Update the chain tip based on database information, i.e.
size_t m_coinsdb_cache_size_bytes
The cache size of the on-disk coins view.
bool DisconnectTip(BlockValidationState &state, DisconnectedBlockTransactions *disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main
Disconnect m_chain's tip.
CCoinsViewCache & CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
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...
int64_t m_total_coinstip_cache
The total number of bytes available for us to use across all in-memory coins caches.
int64_t m_total_coinsdb_cache
The total number of bytes available for us to use across all leveldb coins databases.
bool IsSnapshotValidated() const EXCLUSIVE_LOCKS_REQUIRED(
Is there a snapshot in use and has it been fully validated?
RecursiveMutex & GetMutex() const LOCK_RETURNED(
Alias for cs_main.
int ActiveHeight() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
bool IsSnapshotActive() const
bool LoadBlockIndex() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Load the block tree and coins database from disk, initializing state if we're running with -reindex.
std::optional< uint256 > SnapshotBlockhash() const
Chainstate &InitializeChainstate(CTxMemPool *mempool) EXCLUSIVE_LOCKS_REQUIRED(std::vector< Chainstate * GetAll)()
Instantiate a new chainstate.
void ResetBlockSequenceCounters() EXCLUSIVE_LOCKS_REQUIRED(
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
CTxOut out
unspent transaction output
uint32_t nHeight
at which height this containing transaction was included in the active block chain
DisconnectedBlockTransactions.
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Maintains a tree of blocks (stored in m_block_index) which is consulted to determine where the most-w...
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
void assign(size_type n, const T &val)
static transaction_identifier FromUint256(const uint256 &id)
static const uint256 ZERO
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
BOOST_AUTO_TEST_SUITE_END()
static const unsigned int MAX_DISCONNECTED_TX_POOL_BYTES
Maximum bytes for transactions to store for processing during reorg.
static bool exists(const path &p)
std::optional< uint256 > ReadSnapshotBaseBlockhash(fs::path chaindir)
std::optional< fs::path > FindSnapshotChainstateDir(const fs::path &data_dir)
Return a path to the snapshot-based chainstate dir, if one exists.
#define BOOST_CHECK_EQUAL(v1, v2)
#define BOOST_CHECK(expr)
std::shared_ptr< const CTransaction > CTransactionRef
ChainstateManager & SimulateNodeRestart()
std::tuple< Chainstate *, Chainstate * > SetupSnapshot()
Testing fixture that pre-creates a 100-block REGTEST-mode block chain.
Testing setup that configures a complete environment.
An options struct for ChainstateManager, more ergonomically referred to as ChainstateManager::Options...
const CChainParams & chainparams
std::unique_ptr< ValidationSignals > validation_signals
Issues calls about blocks and transactions.
std::unique_ptr< ChainstateManager > chainman
std::unique_ptr< KernelNotifications > notifications
Issues blocking calls about sync status, errors and warnings.
std::atomic< int > exit_status
util::SignalInterrupt * shutdown
Interrupt object used to track whether node shutdown was requested.
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
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.
#define ASSERT_DEBUG_LOG(message)
static uint256 InsecureRand256()
static uint64_t InsecureRandBits(int bits)
static uint32_t InsecureRand32()
bilingual_str _(const char *psz)
Translation function.
BOOST_FIXTURE_TEST_CASE(chainstatemanager, TestChain100Setup)
Basic tests for ChainstateManager.