mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-02-01 03:01:05 +00:00
9341b5333ad54ccdb7c16802ff06c51b956948e7 blockstorage: make block read hash checks explicit (Lőrinc) 2371b9f4ee0b108ebbb8afedc47d73ce0f97d272 test/bench: verify hash in `ComputeFilter` reads (Lőrinc) 5d235d50d6dd0cc23175a1484e8ebb6cdc6e2183 net: assert block hash in `ProcessGetBlockData` and `ProcessMessage` (Lőrinc) Pull request description: A follow-up to https://github.com/bitcoin/bitcoin/pull/32487#discussion_r2094072165, after which validating the hash of a read block from disk doesn't incur the cost of calculating its hash anymore. ### Summary This PR adds explicit checks that the read block header's hash matches the one we were expecting. ### Context After the previous PR, validating a block's hash during read operations became essentially free. This PR leverages that by requiring callers to provide a block's expected hash (or `std::nullopt`), preventing silent failures caused by corrupted or mismatched data. Most `ReadBlock` usages were updated with expected hashes and now fail on mismatch. ### Changes * added hash assertions in `ProcessGetBlockData` and `ProcessMessage` to validate that the block read from disk matches the expected hash; * updated tests and benchmark to pass the correct block hash to `ReadBlock()`, ensuring the hash validation is tested - or none if we already expect PoW failure; * removed the default value for `expected_hash`, requiring an explicit hash for all block reads. ### Why is the hash still optional (but no longer has a default value) * for header-error tests, where the goal is to trigger failures early in the parsing process; * for out-of-order orphan blocks, where the child hash isn't available before the initial disk read. ACKs for top commit: maflcko: review ACK 9341b5333ad54ccdb7c16802ff06c51b956948e7 🕙 achow101: ACK 9341b5333ad54ccdb7c16802ff06c51b956948e7 hodlinator: ACK 9341b5333ad54ccdb7c16802ff06c51b956948e7 janb84: re ACK 9341b5333ad54ccdb7c16802ff06c51b956948e7 Tree-SHA512: cf1d4fff4c15e3f8898ec284929cb83d7e747125d4ee759e77d369f1716728e843ef98030be32c8d608956a96ae2fbefa0e801200c333b9eefd6c086ec032e1f
71 lines
2.3 KiB
C++
71 lines
2.3 KiB
C++
// Copyright (c) 2023 The Bitcoin Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#include <bench/bench.h>
|
|
#include <bench/data/block413567.raw.h>
|
|
#include <flatfile.h>
|
|
#include <node/blockstorage.h>
|
|
#include <primitives/block.h>
|
|
#include <primitives/transaction.h>
|
|
#include <serialize.h>
|
|
#include <span.h>
|
|
#include <streams.h>
|
|
#include <test/util/setup_common.h>
|
|
#include <validation.h>
|
|
|
|
#include <cassert>
|
|
#include <cstdint>
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
static CBlock CreateTestBlock()
|
|
{
|
|
DataStream stream{benchmark::data::block413567};
|
|
CBlock block;
|
|
stream >> TX_WITH_WITNESS(block);
|
|
return block;
|
|
}
|
|
|
|
static void WriteBlockBench(benchmark::Bench& bench)
|
|
{
|
|
const auto testing_setup{MakeNoLogFileContext<const TestingSetup>(ChainType::MAIN)};
|
|
auto& blockman{testing_setup->m_node.chainman->m_blockman};
|
|
const CBlock block{CreateTestBlock()};
|
|
bench.run([&] {
|
|
const auto pos{blockman.WriteBlock(block, 413'567)};
|
|
assert(!pos.IsNull());
|
|
});
|
|
}
|
|
|
|
static void ReadBlockBench(benchmark::Bench& bench)
|
|
{
|
|
const auto testing_setup{MakeNoLogFileContext<const TestingSetup>(ChainType::MAIN)};
|
|
auto& blockman{testing_setup->m_node.chainman->m_blockman};
|
|
const auto& test_block{CreateTestBlock()};
|
|
const auto& expected_hash{test_block.GetHash()};
|
|
const auto& pos{blockman.WriteBlock(test_block, 413'567)};
|
|
bench.run([&] {
|
|
CBlock block;
|
|
const auto success{blockman.ReadBlock(block, pos, expected_hash)};
|
|
assert(success);
|
|
});
|
|
}
|
|
|
|
static void ReadRawBlockBench(benchmark::Bench& bench)
|
|
{
|
|
const auto testing_setup{MakeNoLogFileContext<const TestingSetup>(ChainType::MAIN)};
|
|
auto& blockman{testing_setup->m_node.chainman->m_blockman};
|
|
const auto pos{blockman.WriteBlock(CreateTestBlock(), 413'567)};
|
|
std::vector<std::byte> block_data;
|
|
blockman.ReadRawBlock(block_data, pos); // warmup
|
|
bench.run([&] {
|
|
const auto success{blockman.ReadRawBlock(block_data, pos)};
|
|
assert(success);
|
|
});
|
|
}
|
|
|
|
BENCHMARK(WriteBlockBench, benchmark::PriorityLevel::HIGH);
|
|
BENCHMARK(ReadBlockBench, benchmark::PriorityLevel::HIGH);
|
|
BENCHMARK(ReadRawBlockBench, benchmark::PriorityLevel::HIGH);
|