support multiple block status checks in CheckBlockDataAvailability
This commit is contained in:
1 parent
3d180d3c7f
commit
881ab4fc82
3 files changed
+25
-4
No files matched your search
@@ -623,10 +623,18 @@ const CBlockIndex& BlockManager::GetFirstBlock(const CBlockIndex& upper_block, u
|
|||||||
return *last_block;
|
return *last_block;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BlockManager::CheckBlockDataAvailability(const CBlockIndex& upper_block, const CBlockIndex& lower_block)
|
bool BlockManager::CheckBlockDataAvailability(const CBlockIndex& upper_block, const CBlockIndex& lower_block, BlockStatus block_status)
|
||||||
{
|
{
|
||||||
if (!(upper_block.nStatus & BLOCK_HAVE_DATA)) return false;
|
if (!(upper_block.nStatus & block_status)) return false;
|
||||||
return &GetFirstBlock(upper_block, BLOCK_HAVE_DATA, &lower_block) == &lower_block;
|
const auto& first_block = GetFirstBlock(upper_block, block_status, &lower_block);
|
||||||
|
// Special case: the genesis block has no undo data
|
||||||
|
if (block_status & BLOCK_HAVE_UNDO && lower_block.nHeight == 0 && first_block.nHeight == 1) {
|
||||||
|
// This might indicate missing data, or it could simply reflect the expected absence of undo data for the genesis block.
|
||||||
|
// To distinguish between the two, check if all required block data *except* undo is available up to the genesis block.
|
||||||
|
BlockStatus flags{block_status & ~BLOCK_HAVE_UNDO};
|
||||||
|
return first_block.pprev && first_block.pprev->nStatus & flags;
|
||||||
|
}
|
||||||
|
return &first_block == &lower_block;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're using -prune with -reindex, then delete block files that will be ignored by the
|
// If we're using -prune with -reindex, then delete block files that will be ignored by the
|
||||||
|
|||||||
@@ -414,7 +414,7 @@ public:
|
|||||||
//! Check if all blocks in the [upper_block, lower_block] range have data available.
|
//! Check if all blocks in the [upper_block, lower_block] range have data available.
|
||||||
//! The caller is responsible for ensuring that lower_block is an ancestor of upper_block
|
//! The caller is responsible for ensuring that lower_block is an ancestor of upper_block
|
||||||
//! (part of the same chain).
|
//! (part of the same chain).
|
||||||
bool CheckBlockDataAvailability(const CBlockIndex& upper_block, const CBlockIndex& lower_block) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
bool CheckBlockDataAvailability(const CBlockIndex& upper_block, const CBlockIndex& lower_block, BlockStatus block_status = BLOCK_HAVE_DATA) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the earliest block with specified `status_mask` flags set after
|
* @brief Returns the earliest block with specified `status_mask` flags set after
|
||||||
|
|||||||
@@ -126,6 +126,14 @@ BOOST_FIXTURE_TEST_CASE(blockmanager_block_data_availability, TestChain100Setup)
|
|||||||
CBlockIndex* lower_block = chainman->ActiveChain()[tip.nHeight / 2];
|
CBlockIndex* lower_block = chainman->ActiveChain()[tip.nHeight / 2];
|
||||||
BOOST_CHECK(blockman.CheckBlockDataAvailability(tip, *lower_block));
|
BOOST_CHECK(blockman.CheckBlockDataAvailability(tip, *lower_block));
|
||||||
|
|
||||||
|
// Ensure we don't fail due to the expected absence of undo data in the genesis block
|
||||||
|
CBlockIndex* upper_block = chainman->ActiveChain()[2];
|
||||||
|
CBlockIndex* genesis = chainman->ActiveChain()[0];
|
||||||
|
BOOST_CHECK(blockman.CheckBlockDataAvailability(*upper_block, *genesis, BlockStatus{BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO}));
|
||||||
|
// Ensure we detect absence of undo data in the first block
|
||||||
|
chainman->ActiveChain()[1]->nStatus &= ~BLOCK_HAVE_UNDO;
|
||||||
|
BOOST_CHECK(!blockman.CheckBlockDataAvailability(tip, *genesis, BlockStatus{BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO}));
|
||||||
|
|
||||||
// Prune half of the blocks
|
// Prune half of the blocks
|
||||||
int height_to_prune = tip.nHeight / 2;
|
int height_to_prune = tip.nHeight / 2;
|
||||||
CBlockIndex* first_available_block = chainman->ActiveChain()[height_to_prune + 1];
|
CBlockIndex* first_available_block = chainman->ActiveChain()[height_to_prune + 1];
|
||||||
@@ -136,6 +144,11 @@ BOOST_FIXTURE_TEST_CASE(blockmanager_block_data_availability, TestChain100Setup)
|
|||||||
BOOST_CHECK_EQUAL(&blockman.GetFirstBlock(tip, BLOCK_HAVE_DATA), first_available_block);
|
BOOST_CHECK_EQUAL(&blockman.GetFirstBlock(tip, BLOCK_HAVE_DATA), first_available_block);
|
||||||
BOOST_CHECK(blockman.CheckBlockDataAvailability(tip, *first_available_block));
|
BOOST_CHECK(blockman.CheckBlockDataAvailability(tip, *first_available_block));
|
||||||
BOOST_CHECK(!blockman.CheckBlockDataAvailability(tip, *last_pruned_block));
|
BOOST_CHECK(!blockman.CheckBlockDataAvailability(tip, *last_pruned_block));
|
||||||
|
|
||||||
|
// Simulate that the first available block is missing undo data and
|
||||||
|
// detect this by using a status mask.
|
||||||
|
first_available_block->nStatus &= ~BLOCK_HAVE_UNDO;
|
||||||
|
BOOST_CHECK(!blockman.CheckBlockDataAvailability(tip, *first_available_block, BlockStatus{BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO}));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(blockmanager_block_data_part, TestChain100Setup)
|
BOOST_FIXTURE_TEST_CASE(blockmanager_block_data_part, TestChain100Setup)
|
||||||
|
|||||||
Reference in new issue
Block a user