mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-09 19:37:27 -03:00
test: adjust chainstate tests to use recognized snapshot base
In future commits, loading the block index while making use of a snapshot is contingent on the snapshot being recognized by chainparams. Ensure all existing unittests that use snapshots use a recognized snapshot (at height 110). Co-authored-by: Ryan Ofsky <ryan@ofsky.org>
This commit is contained in:
parent
1019c39982
commit
49ef778158
2 changed files with 77 additions and 29 deletions
|
@ -30,12 +30,12 @@ using node::BlockManager;
|
|||
using node::KernelNotifications;
|
||||
using node::SnapshotMetadata;
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(validation_chainstatemanager_tests, ChainTestingSetup)
|
||||
BOOST_FIXTURE_TEST_SUITE(validation_chainstatemanager_tests, TestingSetup)
|
||||
|
||||
//! Basic tests for ChainstateManager.
|
||||
//!
|
||||
//! First create a legacy (IBD) chainstate, then create a snapshot chainstate.
|
||||
BOOST_AUTO_TEST_CASE(chainstatemanager)
|
||||
BOOST_FIXTURE_TEST_CASE(chainstatemanager, TestChain100Setup)
|
||||
{
|
||||
ChainstateManager& manager = *m_node.chainman;
|
||||
CTxMemPool& mempool = *m_node.mempool;
|
||||
|
@ -46,14 +46,8 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
|
|||
|
||||
// Create a legacy (IBD) chainstate.
|
||||
//
|
||||
Chainstate& c1 = WITH_LOCK(::cs_main, return manager.InitializeChainstate(&mempool));
|
||||
Chainstate& c1 = manager.ActiveChainstate();
|
||||
chainstates.push_back(&c1);
|
||||
c1.InitCoinsDB(
|
||||
/*cache_size_bytes=*/1 << 23, /*in_memory=*/true, /*should_wipe=*/false);
|
||||
WITH_LOCK(::cs_main, c1.InitCoinsCache(1 << 23));
|
||||
c1.LoadGenesisBlock();
|
||||
BlockValidationState val_state;
|
||||
BOOST_CHECK(c1.ActivateBestChain(val_state, nullptr));
|
||||
|
||||
BOOST_CHECK(!manager.IsSnapshotActive());
|
||||
BOOST_CHECK(WITH_LOCK(::cs_main, return !manager.IsSnapshotValidated()));
|
||||
|
@ -63,8 +57,9 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
|
|||
auto& active_chain = WITH_LOCK(manager.GetMutex(), return manager.ActiveChain());
|
||||
BOOST_CHECK_EQUAL(&active_chain, &c1.m_chain);
|
||||
|
||||
BOOST_CHECK_EQUAL(WITH_LOCK(manager.GetMutex(), return manager.ActiveHeight()), 0);
|
||||
|
||||
// Get to a valid assumeutxo tip (per chainparams);
|
||||
mineBlocks(10);
|
||||
BOOST_CHECK_EQUAL(WITH_LOCK(manager.GetMutex(), return manager.ActiveHeight()), 110);
|
||||
auto active_tip = WITH_LOCK(manager.GetMutex(), return manager.ActiveTip());
|
||||
auto exp_tip = c1.m_chain.Tip();
|
||||
BOOST_CHECK_EQUAL(active_tip, exp_tip);
|
||||
|
@ -77,16 +72,19 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
|
|||
Chainstate& c2 = WITH_LOCK(::cs_main, return manager.ActivateExistingSnapshot(
|
||||
&mempool, snapshot_blockhash));
|
||||
chainstates.push_back(&c2);
|
||||
|
||||
BOOST_CHECK_EQUAL(manager.SnapshotBlockhash().value(), snapshot_blockhash);
|
||||
|
||||
c2.InitCoinsDB(
|
||||
/*cache_size_bytes=*/1 << 23, /*in_memory=*/true, /*should_wipe=*/false);
|
||||
WITH_LOCK(::cs_main, c2.InitCoinsCache(1 << 23));
|
||||
c2.m_chain.SetTip(*active_tip);
|
||||
{
|
||||
LOCK(::cs_main);
|
||||
c2.InitCoinsCache(1 << 23);
|
||||
c2.CoinsTip().SetBestBlock(active_tip->GetBlockHash());
|
||||
c2.setBlockIndexCandidates.insert(manager.m_blockman.LookupBlockIndex(active_tip->GetBlockHash()));
|
||||
c2.LoadChainTip();
|
||||
}
|
||||
BlockValidationState _;
|
||||
BOOST_CHECK(c2.ActivateBestChain(_, nullptr));
|
||||
|
||||
BOOST_CHECK_EQUAL(manager.SnapshotBlockhash().value(), snapshot_blockhash);
|
||||
BOOST_CHECK(manager.IsSnapshotActive());
|
||||
BOOST_CHECK(WITH_LOCK(::cs_main, return !manager.IsSnapshotValidated()));
|
||||
BOOST_CHECK_EQUAL(&c2, &manager.ActiveChainstate());
|
||||
|
@ -97,13 +95,15 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
|
|||
auto& active_chain2 = WITH_LOCK(manager.GetMutex(), return manager.ActiveChain());
|
||||
BOOST_CHECK_EQUAL(&active_chain2, &c2.m_chain);
|
||||
|
||||
BOOST_CHECK_EQUAL(WITH_LOCK(manager.GetMutex(), return manager.ActiveHeight()), 0);
|
||||
BOOST_CHECK_EQUAL(WITH_LOCK(manager.GetMutex(), return manager.ActiveHeight()), 110);
|
||||
mineBlocks(1);
|
||||
BOOST_CHECK_EQUAL(WITH_LOCK(manager.GetMutex(), return manager.ActiveHeight()), 111);
|
||||
BOOST_CHECK_EQUAL(WITH_LOCK(manager.GetMutex(), return c1.m_chain.Height()), 110);
|
||||
|
||||
auto active_tip2 = WITH_LOCK(manager.GetMutex(), return manager.ActiveTip());
|
||||
auto exp_tip2 = c2.m_chain.Tip();
|
||||
BOOST_CHECK_EQUAL(active_tip2, exp_tip2);
|
||||
|
||||
BOOST_CHECK_EQUAL(exp_tip, exp_tip2);
|
||||
BOOST_CHECK_EQUAL(active_tip, active_tip2->pprev);
|
||||
BOOST_CHECK_EQUAL(active_tip, c1.m_chain.Tip());
|
||||
BOOST_CHECK_EQUAL(active_tip2, c2.m_chain.Tip());
|
||||
|
||||
// Let scheduler events finish running to avoid accessing memory that is going to be unloaded
|
||||
SyncWithValidationInterfaceQueue();
|
||||
|
@ -125,9 +125,6 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_rebalance_caches, TestChain100Setup)
|
|||
//
|
||||
Chainstate& c1 = manager.ActiveChainstate();
|
||||
chainstates.push_back(&c1);
|
||||
c1.InitCoinsDB(
|
||||
/*cache_size_bytes=*/1 << 23, /*in_memory=*/true, /*should_wipe=*/false);
|
||||
|
||||
{
|
||||
LOCK(::cs_main);
|
||||
c1.InitCoinsCache(1 << 23);
|
||||
|
@ -431,13 +428,20 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_loadblockindex, TestChain100Setup)
|
|||
|
||||
int num_indexes{0};
|
||||
int num_assumed_valid{0};
|
||||
// Blocks in range [assumed_valid_start_idx, last_assumed_valid_idx) will be
|
||||
// marked as assumed-valid and not having data.
|
||||
const int expected_assumed_valid{20};
|
||||
const int last_assumed_valid_idx{40};
|
||||
const int last_assumed_valid_idx{111};
|
||||
const int assumed_valid_start_idx = last_assumed_valid_idx - expected_assumed_valid;
|
||||
|
||||
// Mine to height 120, past the hardcoded regtest assumeutxo snapshot at
|
||||
// height 110
|
||||
mineBlocks(20);
|
||||
|
||||
CBlockIndex* validated_tip{nullptr};
|
||||
CBlockIndex* assumed_base{nullptr};
|
||||
CBlockIndex* assumed_tip{WITH_LOCK(chainman.GetMutex(), return chainman.ActiveChain().Tip())};
|
||||
BOOST_CHECK_EQUAL(assumed_tip->nHeight, 120);
|
||||
|
||||
auto reload_all_block_indexes = [&]() {
|
||||
// For completeness, we also reset the block sequence counters to
|
||||
|
@ -463,7 +467,7 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_loadblockindex, TestChain100Setup)
|
|||
LOCK(::cs_main);
|
||||
auto index = cs1.m_chain[i];
|
||||
|
||||
// Blocks with heights in range [20, 40) are marked ASSUMED_VALID
|
||||
// Blocks with heights in range [91, 110] are marked ASSUMED_VALID
|
||||
if (i < last_assumed_valid_idx && i >= assumed_valid_start_idx) {
|
||||
index->nStatus = BlockStatus::BLOCK_VALID_TREE | BlockStatus::BLOCK_ASSUMED_VALID;
|
||||
}
|
||||
|
@ -497,10 +501,36 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_loadblockindex, TestChain100Setup)
|
|||
// Set tip of the assume-valid-based chain to the assume-valid block
|
||||
cs2.m_chain.SetTip(*assumed_base);
|
||||
|
||||
// Sanity check test variables.
|
||||
BOOST_CHECK_EQUAL(num_indexes, 121); // 121 total blocks, including genesis
|
||||
BOOST_CHECK_EQUAL(assumed_tip->nHeight, 120); // original chain has height 120
|
||||
BOOST_CHECK_EQUAL(validated_tip->nHeight, 90); // current cs1 chain has height 90
|
||||
BOOST_CHECK_EQUAL(assumed_base->nHeight, 110); // current cs2 chain has height 110
|
||||
|
||||
// Regenerate cs1.setBlockIndexCandidates and cs2.setBlockIndexCandidate and
|
||||
// check contents below.
|
||||
reload_all_block_indexes();
|
||||
|
||||
// The fully validated chain should have the current validated tip
|
||||
// and the assumed valid base as candidates.
|
||||
// The fully validated chain should only have the current validated tip and
|
||||
// the assumed valid base as candidates, blocks 90 and 110. Specifically:
|
||||
//
|
||||
// - It does not have blocks 0-89 because they contain less work than the
|
||||
// chain tip.
|
||||
//
|
||||
// - It has block 90 because it has data and equal work to the chain tip,
|
||||
// (since it is the chain tip).
|
||||
//
|
||||
// - It does not have blocks 91-109 because they do not contain data.
|
||||
//
|
||||
// - It has block 110 even though it does not have data, because
|
||||
// LoadBlockIndex has a special case to always add the snapshot block as a
|
||||
// candidate. The special case is only actually intended to apply to the
|
||||
// snapshot chainstate cs2, not the background chainstate cs1, but it is
|
||||
// written broadly and applies to both.
|
||||
//
|
||||
// - It does not have any blocks after height 110 because cs1 is a background
|
||||
// chainstate, and only blocks where are ancestors of the snapshot block
|
||||
// are added as candidates for the background chainstate.
|
||||
BOOST_CHECK_EQUAL(cs1.setBlockIndexCandidates.size(), 2);
|
||||
BOOST_CHECK_EQUAL(cs1.setBlockIndexCandidates.count(validated_tip), 1);
|
||||
BOOST_CHECK_EQUAL(cs1.setBlockIndexCandidates.count(assumed_base), 1);
|
||||
|
@ -508,8 +538,25 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_loadblockindex, TestChain100Setup)
|
|||
// The assumed-valid tolerant chain has the assumed valid base as a
|
||||
// candidate, but otherwise has none of the assumed-valid (which do not
|
||||
// HAVE_DATA) blocks as candidates.
|
||||
//
|
||||
// Specifically:
|
||||
// - All blocks below height 110 are not candidates, because cs2 chain tip
|
||||
// has height 110 and they have less work than it does.
|
||||
//
|
||||
// - Block 110 is a candidate even though it does not have data, because it
|
||||
// is the snapshot block, which is assumed valid.
|
||||
//
|
||||
// - Blocks 111-120 are added because they have data.
|
||||
|
||||
// Check that block 90 is absent
|
||||
BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.count(validated_tip), 0);
|
||||
// Check that block 109 is absent
|
||||
BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.count(assumed_base->pprev), 0);
|
||||
// Check that block 110 is present
|
||||
BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.count(assumed_base), 1);
|
||||
// Check that block 120 is present
|
||||
BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.count(assumed_tip), 1);
|
||||
// Check that 11 blocks total are present.
|
||||
BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.size(), num_indexes - last_assumed_valid_idx + 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -3539,7 +3539,8 @@ void Chainstate::ResetBlockFailureFlags(CBlockIndex *pindex) {
|
|||
void Chainstate::TryAddBlockIndexCandidate(CBlockIndex* pindex)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
// The block only is a candidate for the most-work-chain if it has more work than our current tip.
|
||||
// The block only is a candidate for the most-work-chain if it has the same
|
||||
// or more work than our current tip.
|
||||
if (m_chain.Tip() != nullptr && setBlockIndexCandidates.value_comp()(pindex, m_chain.Tip())) {
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue