aboutsummaryrefslogtreecommitdiff
path: root/src/test/validation_chainstatemanager_tests.cpp
diff options
context:
space:
mode:
authorMarcoFalke <falke.marco@gmail.com>2021-12-15 11:02:50 +0100
committerMarcoFalke <falke.marco@gmail.com>2021-12-15 11:05:31 +0100
commitb67115dd044d609559a40c27d159aeab3597b251 (patch)
treeaeee2dc7bfeac7bd28e6dbd999b280170a895d8c /src/test/validation_chainstatemanager_tests.cpp
parent7006496a5c03524a7295c70f66ceb8d15fee2919 (diff)
parent2283b9cd1ee0fbd1e8ebc61673b1fe7596199a24 (diff)
downloadbitcoin-b67115dd044d609559a40c27d159aeab3597b251.tar.xz
Merge bitcoin/bitcoin#23174: validation: have LoadBlockIndex account for snapshot use
2283b9cd1ee0fbd1e8ebc61673b1fe7596199a24 test: add tests for LoadBlockIndex when using multiple chainstates (James O'Beirne) 0fd599a51a700c028d6f7ed8067d2d9f6e6a04a5 validation: have LoadBlockIndex account for snapshot use (James O'Beirne) d0c6e61f5dd3b6af818459d9d03b7ba316c5a3f7 validation: don't modify genesis during snapshot load (James O'Beirne) Pull request description: This is part of the [assumeutxo project](https://github.com/bitcoin/bitcoin/projects/11) (parent PR: #15606) --- Currently, `BlockManager::LoadBlockIndex` adds all blocks that have downloaded transactions to the active chain state's `setBlockIndexCandidates` set, ignoring the background chain state. This PR changes ChainstateManager::LoadBlockIndex to update `setBlockIndexCandidates` in the background chain, not just the active chain. In the active chain, the same blocks are added as before. In the background chain, only blocks that have actually been validated, not blocks marked assumed-valid are added so the background chain will continue to download and validate assumed-valid blocks. ACKs for top commit: MarcoFalke: Concept ACK 2283b9cd1ee0fbd1e8ebc61673b1fe7596199a24 🤽 Sjors: utACK 2283b9cd1ee0fbd1e8ebc61673b1fe7596199a24 Tree-SHA512: 7c9a80802df4722d85d12b78d2e7f628ac5f11cb8be66913d5c3230339bd1220c6723805509d4460826a17d1dc04b0ae172eb7d09ac0ea5dc5e41d77975cbd5e
Diffstat (limited to 'src/test/validation_chainstatemanager_tests.cpp')
-rw-r--r--src/test/validation_chainstatemanager_tests.cpp80
1 files changed, 80 insertions, 0 deletions
diff --git a/src/test/validation_chainstatemanager_tests.cpp b/src/test/validation_chainstatemanager_tests.cpp
index a1f70e7e70..e6bd903b92 100644
--- a/src/test/validation_chainstatemanager_tests.cpp
+++ b/src/test/validation_chainstatemanager_tests.cpp
@@ -232,6 +232,9 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_activate_snapshot, TestChain100Setup)
*chainman.ActiveChainstate().m_from_snapshot_blockhash,
*chainman.SnapshotBlockhash());
+ // Ensure that the genesis block was not marked assumed-valid.
+ BOOST_CHECK(!chainman.ActiveChain().Genesis()->IsAssumedValid());
+
const AssumeutxoData& au_data = *ExpectedAssumeutxo(snapshot_height, ::Params());
const CBlockIndex* tip = chainman.ActiveTip();
@@ -309,4 +312,81 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_activate_snapshot, TestChain100Setup)
loaded_snapshot_blockhash);
}
+//! Test LoadBlockIndex behavior when multiple chainstates are in use.
+//!
+//! - First, verfiy that setBlockIndexCandidates is as expected when using a single,
+//! fully-validating chainstate.
+//!
+//! - Then mark a region of the chain BLOCK_ASSUMED_VALID and introduce a second chainstate
+//! that will tolerate assumed-valid blocks. Run LoadBlockIndex() and ensure that the first
+//! chainstate only contains fully validated blocks and the other chainstate contains all blocks,
+//! even those assumed-valid.
+//!
+BOOST_FIXTURE_TEST_CASE(chainstatemanager_loadblockindex, TestChain100Setup)
+{
+ ChainstateManager& chainman = *Assert(m_node.chainman);
+ CTxMemPool& mempool = *m_node.mempool;
+ CChainState& cs1 = chainman.ActiveChainstate();
+
+ int num_indexes{0};
+ int num_assumed_valid{0};
+ const int expected_assumed_valid{20};
+ const int last_assumed_valid_idx{40};
+ const int assumed_valid_start_idx = last_assumed_valid_idx - expected_assumed_valid;
+
+ CBlockIndex* validated_tip{nullptr};
+ CBlockIndex* assumed_tip{chainman.ActiveChain().Tip()};
+
+ auto reload_all_block_indexes = [&]() {
+ for (CChainState* cs : chainman.GetAll()) {
+ LOCK(::cs_main);
+ cs->UnloadBlockIndex();
+ BOOST_CHECK(cs->setBlockIndexCandidates.empty());
+ }
+
+ WITH_LOCK(::cs_main, chainman.LoadBlockIndex());
+ };
+
+ // Ensure that without any assumed-valid BlockIndex entries, all entries are considered
+ // tip candidates.
+ reload_all_block_indexes();
+ BOOST_CHECK_EQUAL(cs1.setBlockIndexCandidates.size(), cs1.m_chain.Height() + 1);
+
+ // Mark some region of the chain assumed-valid.
+ for (int i = 0; i <= cs1.m_chain.Height(); ++i) {
+ auto index = cs1.m_chain[i];
+
+ if (i < last_assumed_valid_idx && i >= assumed_valid_start_idx) {
+ index->nStatus = BlockStatus::BLOCK_VALID_TREE | BlockStatus::BLOCK_ASSUMED_VALID;
+ }
+
+ ++num_indexes;
+ if (index->IsAssumedValid()) ++num_assumed_valid;
+
+ // Note the last fully-validated block as the expected validated tip.
+ if (i == (assumed_valid_start_idx - 1)) {
+ validated_tip = index;
+ BOOST_CHECK(!index->IsAssumedValid());
+ }
+ }
+
+ BOOST_CHECK_EQUAL(expected_assumed_valid, num_assumed_valid);
+
+ CChainState& cs2 = WITH_LOCK(::cs_main,
+ return chainman.InitializeChainstate(&mempool, GetRandHash()));
+
+ reload_all_block_indexes();
+
+ // The fully validated chain only has candidates up to the start of the assumed-valid
+ // blocks.
+ BOOST_CHECK_EQUAL(cs1.setBlockIndexCandidates.count(validated_tip), 1);
+ BOOST_CHECK_EQUAL(cs1.setBlockIndexCandidates.count(assumed_tip), 0);
+ BOOST_CHECK_EQUAL(cs1.setBlockIndexCandidates.size(), assumed_valid_start_idx);
+
+ // The assumed-valid tolerant chain has all blocks as candidates.
+ BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.count(validated_tip), 1);
+ BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.count(assumed_tip), 1);
+ BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.size(), num_indexes);
+}
+
BOOST_AUTO_TEST_SUITE_END()