diff --git a/src/test/blockchain_tests.cpp b/src/test/blockchain_tests.cpp index 4ecc15041cc..9bc05fdccf3 100644 --- a/src/test/blockchain_tests.cpp +++ b/src/test/blockchain_tests.cpp @@ -117,4 +117,36 @@ BOOST_AUTO_TEST_CASE(num_chain_tx_max) BOOST_CHECK_EQUAL(block_index.m_chain_tx_count, std::numeric_limits::max()); } +BOOST_FIXTURE_TEST_CASE(invalidate_block, TestChain100Setup) +{ + const CChain& active{*WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return &Assert(m_node.chainman)->ActiveChain())}; + + // Check BlockStatus when doing InvalidateBlock() + BlockValidationState state; + auto* orig_tip = active.Tip(); + int height_to_invalidate = orig_tip->nHeight - 10; + auto* tip_to_invalidate = active[height_to_invalidate]; + m_node.chainman->ActiveChainstate().InvalidateBlock(state, tip_to_invalidate); + + // tip_to_invalidate just got invalidated, so it's BLOCK_FAILED_VALID + WITH_LOCK(::cs_main, assert(tip_to_invalidate->nStatus & BLOCK_FAILED_VALID)); + WITH_LOCK(::cs_main, assert((tip_to_invalidate->nStatus & BLOCK_FAILED_CHILD) == 0)); + + // check all ancestors of the invalidated block are validated up to BLOCK_VALID_TRANSACTIONS and are not invalid + auto pindex = tip_to_invalidate->pprev; + while (pindex) { + WITH_LOCK(::cs_main, assert(pindex->IsValid(BLOCK_VALID_TRANSACTIONS))); + WITH_LOCK(::cs_main, assert((pindex->nStatus & BLOCK_FAILED_MASK) == 0)); + pindex = pindex->pprev; + } + + // check all descendants of the invalidated block are BLOCK_FAILED_CHILD + pindex = orig_tip; + while (pindex && pindex != tip_to_invalidate) { + WITH_LOCK(::cs_main, assert((pindex->nStatus & BLOCK_FAILED_VALID) == 0)); + WITH_LOCK(::cs_main, assert(pindex->nStatus & BLOCK_FAILED_CHILD)); + pindex = pindex->pprev; + } +} + BOOST_AUTO_TEST_SUITE_END()