refactor, blockstorage: Generalize GetFirstStoredBlock

GetFirstStoredBlock is generalized to check for any data status with a
status mask that needs to be passed as a parameter. To reflect this the
function is also renamed to GetFirstBlock.

Co-authored-by: stickies-v <stickies-v@protonmail.com>
This commit is contained in:
Fabian Jahr
2024-03-17 15:38:04 +01:00
parent 3aaf7328eb
commit 96b4facc91
6 changed files with 93 additions and 14 deletions

View File

@@ -595,12 +595,12 @@ bool BlockManager::IsBlockPruned(const CBlockIndex& block)
return m_have_pruned && !(block.nStatus & BLOCK_HAVE_DATA) && (block.nTx > 0);
}
const CBlockIndex* BlockManager::GetFirstStoredBlock(const CBlockIndex& upper_block, const CBlockIndex* lower_block)
const CBlockIndex* BlockManager::GetFirstBlock(const CBlockIndex& upper_block, uint32_t status_mask, const CBlockIndex* lower_block) const
{
AssertLockHeld(::cs_main);
const CBlockIndex* last_block = &upper_block;
assert(last_block->nStatus & BLOCK_HAVE_DATA); // 'upper_block' must have data
while (last_block->pprev && (last_block->pprev->nStatus & BLOCK_HAVE_DATA)) {
assert((last_block->nStatus & status_mask) == status_mask); // 'upper_block' must satisfy the status mask
while (last_block->pprev && ((last_block->pprev->nStatus & status_mask) == status_mask)) {
if (lower_block) {
// Return if we reached the lower_block
if (last_block == lower_block) return lower_block;
@@ -617,7 +617,7 @@ const CBlockIndex* BlockManager::GetFirstStoredBlock(const CBlockIndex& upper_bl
bool BlockManager::CheckBlockDataAvailability(const CBlockIndex& upper_block, const CBlockIndex& lower_block)
{
if (!(upper_block.nStatus & BLOCK_HAVE_DATA)) return false;
return GetFirstStoredBlock(upper_block, &lower_block) == &lower_block;
return GetFirstBlock(upper_block, BLOCK_HAVE_DATA, &lower_block) == &lower_block;
}
// If we're using -prune with -reindex, then delete block files that will be ignored by the

View File

@@ -335,10 +335,33 @@ public:
//! (part of the same chain).
bool CheckBlockDataAvailability(const CBlockIndex& upper_block LIFETIMEBOUND, const CBlockIndex& lower_block LIFETIMEBOUND) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
//! Find the first stored ancestor of start_block immediately after the last
//! pruned ancestor. Return value will never be null. Caller is responsible
//! for ensuring that start_block has data is not pruned.
const CBlockIndex* GetFirstStoredBlock(const CBlockIndex& start_block LIFETIMEBOUND, const CBlockIndex* lower_block=nullptr) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
/**
* @brief Returns the earliest block with specified `status_mask` flags set after
* the latest block _not_ having those flags.
*
* This function starts from `upper_block`, which must have all
* `status_mask` flags set, and iterates backwards through its ancestors. It
* continues as long as each block has all `status_mask` flags set, until
* reaching the oldest ancestor or `lower_block`.
*
* @pre `upper_block` must have all `status_mask` flags set.
* @pre `lower_block` must be null or an ancestor of `upper_block`
*
* @param upper_block The starting block for the search, which must have all
* `status_mask` flags set.
* @param status_mask Bitmask specifying required status flags.
* @param lower_block The earliest possible block to return. If null, the
* search can extend to the genesis block.
*
* @return A non-null pointer to the earliest block between `upper_block`
* and `lower_block`, inclusive, such that every block between the
* returned block and `upper_block` has `status_mask` flags set.
*/
const CBlockIndex* GetFirstBlock(
const CBlockIndex& upper_block LIFETIMEBOUND,
uint32_t status_mask,
const CBlockIndex* lower_block = nullptr
) const EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
/** True if any block files have ever been pruned. */
bool m_have_pruned = false;