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

Code before:
    }

    try {
        // Read block
        SpanReader{block_data} >> TX_WITH_WITNESS(block);
    } catch (const std::exception& e) {
        LogError("Deserialize or I/O error - %s at %s while reading block", e.what(), pos.ToString());
        return false;
    }

    const auto block_hash{block.GetHash()};

    // Check the header
    if (!CheckProofOfWork(block_hash, block.nBits, GetConsensus())) {
        LogError("Errors in block header at %s while reading block", pos.ToString());
        return false;
    }

    // Signet only: check block solution
    if (GetConsensus().signet_blocks && !CheckSignetBlockSolution(block, GetConsensus())) {
        LogError("Errors in block solution at %s while reading block", pos.ToString());
        return false;
    }

    if (expected_hash && block_hash != *expected_hash) {
        LogError("GetHash() doesn't match index at %s while reading block", pos.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<uint8_t>& 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;

Review comment (bug):
This error log change no longer provides info about the index that doesn't match.

Examples from the unit test log:

`$ ./build/bin/test_bitcoin --run_test=blockmanager_tests -l test_suite -- DEBUG_LOG_OUT`

before
```
025-05-23T18:42:55.808136Z (mocktime: 2020-08-31T15:34:12Z) [test] [node/blockstorage.cpp:1033] [ReadBlock] [error] GetHash() doesn't match index for CBlockIndex(pprev=0x6000019085e0, nHeight=100, merkle=851b8e14be513191d6dd7df5ac3c997c2b0b1f58c99143905eac61b296d01169, hashBlock=0000000000000000000000000000000000000000000000000000000000000001) at FlatFilePos(nFile=0, nPos=27015) while reading block

```
after
```
2025-05-23T18:44:21.481359Z (mocktime: 2020-08-31T15:34:12Z) [test] [node/blockstorage.cpp:1026] [ReadBlock] [error] GetHash() doesn't match index at FlatFilePos(nFile=0, nPos=27015) while reading block
```


Code after:
    }

    try {
        // Read block
        SpanReader{block_data} >> TX_WITH_WITNESS(block);
    } catch (const std::exception& e) {
        LogError("Deserialize or I/O error - %s at %s while reading block", e.what(), pos.ToString());
        return false;
    }

    const auto block_hash{block.GetHash()};

    // Check the header
    if (!CheckProofOfWork(block_hash, block.nBits, GetConsensus())) {
        LogError("Errors in block header at %s while reading block", pos.ToString());
        return false;
    }

    // Signet only: check block solution
    if (GetConsensus().signet_blocks && !CheckSignetBlockSolution(block, GetConsensus())) {
        LogError("Errors in block solution at %s while reading block", pos.ToString());
        return false;
    }

    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<uint8_t>& 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());