Repository: bitcoin/bitcoin
File: src/node/blockstorage.cpp (C++)

Code before:

    if (expected_hash && block_hash != *expected_hash) {
        LogError("GetHash() doesn't match index at %s while reading block (%s != %s)",
                 pos.ToString(), block_hash.ToString(), expected_hash->ToString());
        return false;
    }

    return true;
}

bool BlockManager::ReadBlock(CBlock& block, const CBlockIndex& index) const
{
    const FlatFilePos block_pos{WITH_LOCK(cs_main, return index.GetBlockPos())};
    return ReadBlock(block, block_pos, index.GetBlockHash());
}

bool BlockManager::ReadRawBlock(std::vector<std::byte>& block, const FlatFilePos& pos) const
{
    if (pos.nPos < STORAGE_HEADER_BYTES) {
        // If nPos is less than STORAGE_HEADER_BYTES, we can't read the header that precedes the block data
        // This would cause an unsigned integer underflow when trying to position the file cursor
        // This can happen after pruning or default constructed positions
        LogError("Failed for %s while reading raw block storage header", pos.ToString());
        return false;
    }
    AutoFile filein{OpenBlockFile({pos.nFile, pos.nPos - STORAGE_HEADER_BYTES}, /*fReadOnly=*/true)};
    if (filein.IsNull()) {
        LogError("OpenBlockFile failed for %s while reading raw block", pos.ToString());
        return false;
    }

    try {
        MessageStartChars blk_start;
        unsigned int blk_size;

        filein >> blk_start >> blk_size;

        if (blk_start != GetParams().MessageStart()) {
            LogError("Block magic mismatch for %s: %s versus expected %s while reading raw block",
                pos.ToString(), HexStr(blk_start), HexStr(GetParams().MessageStart()));
            return false;
        }

        if (blk_size > MAX_SIZE) {
            LogError("Block data is larger than maximum deserialization size for %s: %s versus %s while reading raw block",
                pos.ToString(), blk_size, MAX_SIZE);
            return false;
        }

        block.resize(blk_size); // Zeroing of memory is intentional here
        filein.read(block);

Review comment (suggestion):
there's a **lot** happening in a single commit - please consider splitting the low risk changes such as this line from introducing a new feature or a doc change. It would help guide the reviewers if it were split into trivial-to-review chunks where the commit message explains the thinking.

Code after:

    if (expected_hash && block_hash != *expected_hash) {
        LogError("GetHash() doesn't match index at %s while reading block (%s != %s)",
                 pos.ToString(), block_hash.ToString(), expected_hash->ToString());
        return false;
    }

    return true;
}

bool BlockManager::ReadBlock(CBlock& block, const CBlockIndex& index) const
{
    const FlatFilePos block_pos{WITH_LOCK(cs_main, return index.GetBlockPos())};
    return ReadBlock(block, block_pos, index.GetBlockHash());
}

BlockManager::ReadRawBlockResult BlockManager::ReadRawBlock(const FlatFilePos& pos, std::optional<std::pair<size_t, size_t>> block_part) const
{
    if (pos.nPos < STORAGE_HEADER_BYTES) {
        // If nPos is less than STORAGE_HEADER_BYTES, we can't read the header that precedes the block data
        // This would cause an unsigned integer underflow when trying to position the file cursor
        // This can happen after pruning or default constructed positions
        LogError("Failed for %s while reading raw block storage header", pos.ToString());
        return util::Unexpected{ReadRawError::IO};
    }
    AutoFile filein{OpenBlockFile({pos.nFile, pos.nPos - STORAGE_HEADER_BYTES}, /*fReadOnly=*/true)};
    if (filein.IsNull()) {
        LogError("OpenBlockFile failed for %s while reading raw block", pos.ToString());
        return util::Unexpected{ReadRawError::IO};
    }

    try {
        MessageStartChars blk_start;
        unsigned int blk_size;

        filein >> blk_start >> blk_size;

        if (blk_start != GetParams().MessageStart()) {
            LogError("Block magic mismatch for %s: %s versus expected %s while reading raw block",
                pos.ToString(), HexStr(blk_start), HexStr(GetParams().MessageStart()));
            return util::Unexpected{ReadRawError::IO};
        }

        if (blk_size > MAX_SIZE) {
            LogError("Block data is larger than maximum deserialization size for %s: %s versus %s while reading raw block",
                pos.ToString(), blk_size, MAX_SIZE);
            return util::Unexpected{ReadRawError::IO};
        }

        if (block_part) {
            const auto [offset, size]{*block_part};