diff options
author | Ava Chow <github@achow101.com> | 2024-07-10 15:27:05 -0400 |
---|---|---|
committer | Ava Chow <github@achow101.com> | 2024-07-10 15:27:05 -0400 |
commit | f4849f692270f341f353806c44f2c1849879a6bf (patch) | |
tree | dd317b79aa760a8fea9195d162fb2d075e89c8e5 /src/node | |
parent | 394651ff10ff00d3e779b2df8645547ee2b1934c (diff) | |
parent | 8789dc8f315a9d9ad7142d831bc9412f780248e7 (diff) |
Merge bitcoin/bitcoin#29668: prune, rpc: Check undo data when finding pruneheight
8789dc8f315a9d9ad7142d831bc9412f780248e7 doc: Add note to getblockfrompeer on missing undo data (Fabian Jahr)
4a1975008b602aeacdad9a74d1837a7455148074 rpc: Make pruneheight also reflect undo data presence (Fabian Jahr)
96b4facc912927305b06a233cb8b36e7e5964c08 refactor, blockstorage: Generalize GetFirstStoredBlock (Fabian Jahr)
Pull request description:
The function `GetFirstStoredBlock()` helps us find the first block for which we have data. So far this function only looked for a block with `BLOCK_HAVE_DATA`. However, this doesn't mean that we also have the undo data of that block, and undo data might be required for what a user would like to do with those blocks. One example of how this might happen is if some blocks were fetched using the `getblockfrompeer` RPC. Blocks fetched from a peer will have data but no undo data.
The first commit here allows `GetFirstStoredBlock()` to check for undo data as well by passing a parameter. This alone is useful for #29553 and I would use it there.
In the second commit I am applying the undo check to the RPCs that report `pruneheight` to the user. I find this much more intuitive because I think the user expects to be able to do all operations on blocks up until the `pruneheight` but that is not the case if undo data is missing. I personally ran into this once before and now again when testing for assumeutxo when I had used `getblockfrompeer`. The following commit adds test coverage for this change of behavior.
The last commit adds a note in the docs of `getblockfrompeer` that undo data will not be available.
ACKs for top commit:
achow101:
ACK 8789dc8f315a9d9ad7142d831bc9412f780248e7
furszy:
Code review ACK 8789dc8f315a9d9ad7142d831bc9412f780248e7.
stickies-v:
ACK 8789dc8f315a9d9ad7142d831bc9412f780248e7
Tree-SHA512: 90ae8bdd07a496ade579aa25240609c61c9ed173ad38d30533f6c631fe674e5a41727478ade69ca4b71a571ad94c9da4b33ebba6b5d8821109313c2de3bdfb3d
Diffstat (limited to 'src/node')
-rw-r--r-- | src/node/blockstorage.cpp | 8 | ||||
-rw-r--r-- | src/node/blockstorage.h | 31 |
2 files changed, 31 insertions, 8 deletions
diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index fb62e78138..80aceb312a 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -594,12 +594,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; @@ -616,7 +616,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 diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index 108a08a72b..0a46d79764 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -372,10 +372,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; |