Repository: bitcoin/bitcoin
File: src/index/blockfilterindex.cpp (C++)

Code before:
    }
    if (file.fclose() != 0) {
        LogError("Failed to close filter file %d after commit: %s", pos.nFile, SysErrorString(errno));
        return false;
    }

    batch.Write(DB_FILTER_POS, pos);
    return true;
}

bool BlockFilterIndex::ReadFilterFromDisk(const FlatFilePos& pos, const uint256& hash, BlockFilter& filter) const
{
    AutoFile filein{m_filter_fileseq->Open(pos, true)};
    if (filein.IsNull()) {
        return false;
    }

    // Check that the hash of the encoded_filter matches the one stored in the db.
    uint256 block_hash;
    std::vector<uint8_t> encoded_filter;
    try {
        filein >> block_hash >> encoded_filter;
        if (Hash(encoded_filter) != hash) {
            LogError("Checksum mismatch in filter decode.");
            return false;
        }
        filter = BlockFilter(GetFilterType(), block_hash, std::move(encoded_filter), /*skip_decode_check=*/true);
    }
    catch (const std::exception& e) {
        LogError("Failed to deserialize block filter from disk: %s", e.what());
        return false;
    }

    return true;
}

size_t BlockFilterIndex::WriteFilterToDisk(FlatFilePos& pos, const BlockFilter& filter)
{
    assert(filter.GetFilterType() == GetFilterType());

    size_t data_size =
        GetSerializeSize(filter.GetBlockHash()) +
        GetSerializeSize(filter.GetEncodedFilter());

    // If writing the filter would overflow the file, flush and move to the next one.
    if (pos.nPos + data_size > MAX_FLTR_FILE_SIZE) {
        AutoFile last_file{m_filter_fileseq->Open(pos)};
        if (last_file.IsNull()) {
            LogError("Failed to open filter file %d", pos.nFile);
            return 0;
        }

Review comment (suggestion):
`MAX_FLTR_FILE_SIZE` is only used here
https://github.com/bitcoin/bitcoin/blob/fab75c2d0332fdb25030abb441363478cd486dc5/src/index/blockfilterindex.cpp#L39
we should adjust its type to match the usage
```C++
constexpr uint32_t FLTR_FILE_CHUNK_SIZE{0x100000}; // 1 MiB
```

Code after:
    try {
        filein >> block_hash >> encoded_filter;
        if (Hash(encoded_filter) != hash) {
            LogError("Checksum mismatch in filter decode.");
            return false;
        }
        filter = BlockFilter(GetFilterType(), block_hash, std::move(encoded_filter), /*skip_decode_check=*/true);
    }
    catch (const std::exception& e) {
        LogError("Failed to deserialize block filter from disk: %s", e.what());
        return false;
    }

    return true;
}

size_t BlockFilterIndex::WriteFilterToDisk(FlatFilePos& pos, const BlockFilter& filter)
{
    assert(filter.GetFilterType() == GetFilterType());

    uint64_t data_size{
        GetSerializeSize(filter.GetBlockHash()) +
        GetSerializeSize(filter.GetEncodedFilter())};

    // If writing the filter would overflow the file, flush and move to the next one.
    if (pos.nPos + data_size > MAX_FLTR_FILE_SIZE) {
        AutoFile last_file{m_filter_fileseq->Open(pos)};
        if (last_file.IsNull()) {
            LogError("Failed to open filter file %d", pos.nFile);
            return 0;
        }
        if (!last_file.Truncate(pos.nPos)) {
            LogError("Failed to truncate filter file %d", pos.nFile);
            return 0;
        }
        if (!last_file.Commit()) {
            LogError("Failed to commit filter file %d", pos.nFile);
            (void)last_file.fclose();
            return 0;
        }
        if (last_file.fclose() != 0) {
            LogError("Failed to close filter file %d after commit: %s", pos.nFile, SysErrorString(errno));
            return 0;
        }

        pos.nFile++;
        pos.nPos = 0;
    }

    // Pre-allocate sufficient space for filter data.
    bool out_of_space;