Skip to content

Commit 49ef778

Browse files
jamesobryanofsky
andcommitted
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 <[email protected]>
1 parent 1019c39 commit 49ef778

File tree

2 files changed

+77
-29
lines changed

2 files changed

+77
-29
lines changed

src/test/validation_chainstatemanager_tests.cpp

Lines changed: 75 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ using node::BlockManager;
3030
using node::KernelNotifications;
3131
using node::SnapshotMetadata;
3232

33-
BOOST_FIXTURE_TEST_SUITE(validation_chainstatemanager_tests, ChainTestingSetup)
33+
BOOST_FIXTURE_TEST_SUITE(validation_chainstatemanager_tests, TestingSetup)
3434

3535
//! Basic tests for ChainstateManager.
3636
//!
3737
//! First create a legacy (IBD) chainstate, then create a snapshot chainstate.
38-
BOOST_AUTO_TEST_CASE(chainstatemanager)
38+
BOOST_FIXTURE_TEST_CASE(chainstatemanager, TestChain100Setup)
3939
{
4040
ChainstateManager& manager = *m_node.chainman;
4141
CTxMemPool& mempool = *m_node.mempool;
@@ -46,14 +46,8 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
4646

4747
// Create a legacy (IBD) chainstate.
4848
//
49-
Chainstate& c1 = WITH_LOCK(::cs_main, return manager.InitializeChainstate(&mempool));
49+
Chainstate& c1 = manager.ActiveChainstate();
5050
chainstates.push_back(&c1);
51-
c1.InitCoinsDB(
52-
/*cache_size_bytes=*/1 << 23, /*in_memory=*/true, /*should_wipe=*/false);
53-
WITH_LOCK(::cs_main, c1.InitCoinsCache(1 << 23));
54-
c1.LoadGenesisBlock();
55-
BlockValidationState val_state;
56-
BOOST_CHECK(c1.ActivateBestChain(val_state, nullptr));
5751

5852
BOOST_CHECK(!manager.IsSnapshotActive());
5953
BOOST_CHECK(WITH_LOCK(::cs_main, return !manager.IsSnapshotValidated()));
@@ -63,8 +57,9 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
6357
auto& active_chain = WITH_LOCK(manager.GetMutex(), return manager.ActiveChain());
6458
BOOST_CHECK_EQUAL(&active_chain, &c1.m_chain);
6559

66-
BOOST_CHECK_EQUAL(WITH_LOCK(manager.GetMutex(), return manager.ActiveHeight()), 0);
67-
60+
// Get to a valid assumeutxo tip (per chainparams);
61+
mineBlocks(10);
62+
BOOST_CHECK_EQUAL(WITH_LOCK(manager.GetMutex(), return manager.ActiveHeight()), 110);
6863
auto active_tip = WITH_LOCK(manager.GetMutex(), return manager.ActiveTip());
6964
auto exp_tip = c1.m_chain.Tip();
7065
BOOST_CHECK_EQUAL(active_tip, exp_tip);
@@ -77,16 +72,19 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
7772
Chainstate& c2 = WITH_LOCK(::cs_main, return manager.ActivateExistingSnapshot(
7873
&mempool, snapshot_blockhash));
7974
chainstates.push_back(&c2);
80-
81-
BOOST_CHECK_EQUAL(manager.SnapshotBlockhash().value(), snapshot_blockhash);
82-
8375
c2.InitCoinsDB(
8476
/*cache_size_bytes=*/1 << 23, /*in_memory=*/true, /*should_wipe=*/false);
85-
WITH_LOCK(::cs_main, c2.InitCoinsCache(1 << 23));
86-
c2.m_chain.SetTip(*active_tip);
77+
{
78+
LOCK(::cs_main);
79+
c2.InitCoinsCache(1 << 23);
80+
c2.CoinsTip().SetBestBlock(active_tip->GetBlockHash());
81+
c2.setBlockIndexCandidates.insert(manager.m_blockman.LookupBlockIndex(active_tip->GetBlockHash()));
82+
c2.LoadChainTip();
83+
}
8784
BlockValidationState _;
8885
BOOST_CHECK(c2.ActivateBestChain(_, nullptr));
8986

87+
BOOST_CHECK_EQUAL(manager.SnapshotBlockhash().value(), snapshot_blockhash);
9088
BOOST_CHECK(manager.IsSnapshotActive());
9189
BOOST_CHECK(WITH_LOCK(::cs_main, return !manager.IsSnapshotValidated()));
9290
BOOST_CHECK_EQUAL(&c2, &manager.ActiveChainstate());
@@ -97,13 +95,15 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
9795
auto& active_chain2 = WITH_LOCK(manager.GetMutex(), return manager.ActiveChain());
9896
BOOST_CHECK_EQUAL(&active_chain2, &c2.m_chain);
9997

100-
BOOST_CHECK_EQUAL(WITH_LOCK(manager.GetMutex(), return manager.ActiveHeight()), 0);
98+
BOOST_CHECK_EQUAL(WITH_LOCK(manager.GetMutex(), return manager.ActiveHeight()), 110);
99+
mineBlocks(1);
100+
BOOST_CHECK_EQUAL(WITH_LOCK(manager.GetMutex(), return manager.ActiveHeight()), 111);
101+
BOOST_CHECK_EQUAL(WITH_LOCK(manager.GetMutex(), return c1.m_chain.Height()), 110);
101102

102103
auto active_tip2 = WITH_LOCK(manager.GetMutex(), return manager.ActiveTip());
103-
auto exp_tip2 = c2.m_chain.Tip();
104-
BOOST_CHECK_EQUAL(active_tip2, exp_tip2);
105-
106-
BOOST_CHECK_EQUAL(exp_tip, exp_tip2);
104+
BOOST_CHECK_EQUAL(active_tip, active_tip2->pprev);
105+
BOOST_CHECK_EQUAL(active_tip, c1.m_chain.Tip());
106+
BOOST_CHECK_EQUAL(active_tip2, c2.m_chain.Tip());
107107

108108
// Let scheduler events finish running to avoid accessing memory that is going to be unloaded
109109
SyncWithValidationInterfaceQueue();
@@ -125,9 +125,6 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_rebalance_caches, TestChain100Setup)
125125
//
126126
Chainstate& c1 = manager.ActiveChainstate();
127127
chainstates.push_back(&c1);
128-
c1.InitCoinsDB(
129-
/*cache_size_bytes=*/1 << 23, /*in_memory=*/true, /*should_wipe=*/false);
130-
131128
{
132129
LOCK(::cs_main);
133130
c1.InitCoinsCache(1 << 23);
@@ -431,13 +428,20 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_loadblockindex, TestChain100Setup)
431428

432429
int num_indexes{0};
433430
int num_assumed_valid{0};
431+
// Blocks in range [assumed_valid_start_idx, last_assumed_valid_idx) will be
432+
// marked as assumed-valid and not having data.
434433
const int expected_assumed_valid{20};
435-
const int last_assumed_valid_idx{40};
434+
const int last_assumed_valid_idx{111};
436435
const int assumed_valid_start_idx = last_assumed_valid_idx - expected_assumed_valid;
437436

437+
// Mine to height 120, past the hardcoded regtest assumeutxo snapshot at
438+
// height 110
439+
mineBlocks(20);
440+
438441
CBlockIndex* validated_tip{nullptr};
439442
CBlockIndex* assumed_base{nullptr};
440443
CBlockIndex* assumed_tip{WITH_LOCK(chainman.GetMutex(), return chainman.ActiveChain().Tip())};
444+
BOOST_CHECK_EQUAL(assumed_tip->nHeight, 120);
441445

442446
auto reload_all_block_indexes = [&]() {
443447
// For completeness, we also reset the block sequence counters to
@@ -463,7 +467,7 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_loadblockindex, TestChain100Setup)
463467
LOCK(::cs_main);
464468
auto index = cs1.m_chain[i];
465469

466-
// Blocks with heights in range [20, 40) are marked ASSUMED_VALID
470+
// Blocks with heights in range [91, 110] are marked ASSUMED_VALID
467471
if (i < last_assumed_valid_idx && i >= assumed_valid_start_idx) {
468472
index->nStatus = BlockStatus::BLOCK_VALID_TREE | BlockStatus::BLOCK_ASSUMED_VALID;
469473
}
@@ -497,19 +501,62 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_loadblockindex, TestChain100Setup)
497501
// Set tip of the assume-valid-based chain to the assume-valid block
498502
cs2.m_chain.SetTip(*assumed_base);
499503

504+
// Sanity check test variables.
505+
BOOST_CHECK_EQUAL(num_indexes, 121); // 121 total blocks, including genesis
506+
BOOST_CHECK_EQUAL(assumed_tip->nHeight, 120); // original chain has height 120
507+
BOOST_CHECK_EQUAL(validated_tip->nHeight, 90); // current cs1 chain has height 90
508+
BOOST_CHECK_EQUAL(assumed_base->nHeight, 110); // current cs2 chain has height 110
509+
510+
// Regenerate cs1.setBlockIndexCandidates and cs2.setBlockIndexCandidate and
511+
// check contents below.
500512
reload_all_block_indexes();
501513

502-
// The fully validated chain should have the current validated tip
503-
// and the assumed valid base as candidates.
514+
// The fully validated chain should only have the current validated tip and
515+
// the assumed valid base as candidates, blocks 90 and 110. Specifically:
516+
//
517+
// - It does not have blocks 0-89 because they contain less work than the
518+
// chain tip.
519+
//
520+
// - It has block 90 because it has data and equal work to the chain tip,
521+
// (since it is the chain tip).
522+
//
523+
// - It does not have blocks 91-109 because they do not contain data.
524+
//
525+
// - It has block 110 even though it does not have data, because
526+
// LoadBlockIndex has a special case to always add the snapshot block as a
527+
// candidate. The special case is only actually intended to apply to the
528+
// snapshot chainstate cs2, not the background chainstate cs1, but it is
529+
// written broadly and applies to both.
530+
//
531+
// - It does not have any blocks after height 110 because cs1 is a background
532+
// chainstate, and only blocks where are ancestors of the snapshot block
533+
// are added as candidates for the background chainstate.
504534
BOOST_CHECK_EQUAL(cs1.setBlockIndexCandidates.size(), 2);
505535
BOOST_CHECK_EQUAL(cs1.setBlockIndexCandidates.count(validated_tip), 1);
506536
BOOST_CHECK_EQUAL(cs1.setBlockIndexCandidates.count(assumed_base), 1);
507537

508538
// The assumed-valid tolerant chain has the assumed valid base as a
509539
// candidate, but otherwise has none of the assumed-valid (which do not
510540
// HAVE_DATA) blocks as candidates.
541+
//
542+
// Specifically:
543+
// - All blocks below height 110 are not candidates, because cs2 chain tip
544+
// has height 110 and they have less work than it does.
545+
//
546+
// - Block 110 is a candidate even though it does not have data, because it
547+
// is the snapshot block, which is assumed valid.
548+
//
549+
// - Blocks 111-120 are added because they have data.
550+
551+
// Check that block 90 is absent
511552
BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.count(validated_tip), 0);
553+
// Check that block 109 is absent
554+
BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.count(assumed_base->pprev), 0);
555+
// Check that block 110 is present
556+
BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.count(assumed_base), 1);
557+
// Check that block 120 is present
512558
BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.count(assumed_tip), 1);
559+
// Check that 11 blocks total are present.
513560
BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.size(), num_indexes - last_assumed_valid_idx + 1);
514561
}
515562

src/validation.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3539,7 +3539,8 @@ void Chainstate::ResetBlockFailureFlags(CBlockIndex *pindex) {
35393539
void Chainstate::TryAddBlockIndexCandidate(CBlockIndex* pindex)
35403540
{
35413541
AssertLockHeld(cs_main);
3542-
// The block only is a candidate for the most-work-chain if it has more work than our current tip.
3542+
// The block only is a candidate for the most-work-chain if it has the same
3543+
// or more work than our current tip.
35433544
if (m_chain.Tip() != nullptr && setBlockIndexCandidates.value_comp()(pindex, m_chain.Tip())) {
35443545
return;
35453546
}

0 commit comments

Comments
 (0)