Skip to content

Commit 9bd9aee

Browse files
committed
Merge bitcoin/bitcoin#32487: blocks: avoid recomputing block header hash in ReadBlock
09ee8b7 node: avoid recomputing block hash in `ReadBlock` (Lőrinc) 2bf1732 test: exercise `ReadBlock` hash‑mismatch path (Lőrinc) Pull request description: Eliminate one block header hash calculation per block-read by reusing the hash for: * proof‑of‑work verification; * (optional) integrity check against the supplied hash. This part of the code wasn't covered by tests either, so the first commit exercises this part first, before pushing the validation to the delegate method. ACKs for top commit: maflcko: lgtm ACK 09ee8b7 achow101: ACK 09ee8b7 jonatack: ACK 09ee8b7 pinheadmz: ACK 09ee8b7 Tree-SHA512: 43fe51b478ea574b6d4c952684b13ca54fb8cbd67c3b6c136f460122d9ee953cc70b88778537117eecea71ccb8d88311faeac21b866e11d117f1145973204ed4
2 parents 4173805 + 09ee8b7 commit 9bd9aee

File tree

3 files changed

+23
-12
lines changed

3 files changed

+23
-12
lines changed

src/node/blockstorage.cpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
#include <cstddef>
4040
#include <map>
41+
#include <optional>
4142
#include <unordered_map>
4243

4344
namespace kernel {
@@ -989,7 +990,7 @@ bool BlockManager::WriteBlockUndo(const CBlockUndo& blockundo, BlockValidationSt
989990
return true;
990991
}
991992

992-
bool BlockManager::ReadBlock(CBlock& block, const FlatFilePos& pos) const
993+
bool BlockManager::ReadBlock(CBlock& block, const FlatFilePos& pos, const std::optional<uint256>& expected_hash) const
993994
{
994995
block.SetNull();
995996

@@ -1007,8 +1008,10 @@ bool BlockManager::ReadBlock(CBlock& block, const FlatFilePos& pos) const
10071008
return false;
10081009
}
10091010

1011+
const auto block_hash{block.GetHash()};
1012+
10101013
// Check the header
1011-
if (!CheckProofOfWork(block.GetHash(), block.nBits, GetConsensus())) {
1014+
if (!CheckProofOfWork(block_hash, block.nBits, GetConsensus())) {
10121015
LogError("Errors in block header at %s while reading block", pos.ToString());
10131016
return false;
10141017
}
@@ -1019,21 +1022,19 @@ bool BlockManager::ReadBlock(CBlock& block, const FlatFilePos& pos) const
10191022
return false;
10201023
}
10211024

1025+
if (expected_hash && block_hash != *expected_hash) {
1026+
LogError("GetHash() doesn't match index at %s while reading block (%s != %s)",
1027+
pos.ToString(), block_hash.ToString(), expected_hash->ToString());
1028+
return false;
1029+
}
1030+
10221031
return true;
10231032
}
10241033

10251034
bool BlockManager::ReadBlock(CBlock& block, const CBlockIndex& index) const
10261035
{
10271036
const FlatFilePos block_pos{WITH_LOCK(cs_main, return index.GetBlockPos())};
1028-
1029-
if (!ReadBlock(block, block_pos)) {
1030-
return false;
1031-
}
1032-
if (block.GetHash() != index.GetBlockHash()) {
1033-
LogError("GetHash() doesn't match index for %s at %s while reading block", index.ToString(), block_pos.ToString());
1034-
return false;
1035-
}
1036-
return true;
1037+
return ReadBlock(block, block_pos, index.GetBlockHash());
10371038
}
10381039

10391040
bool BlockManager::ReadRawBlock(std::vector<uint8_t>& block, const FlatFilePos& pos) const

src/node/blockstorage.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ class BlockManager
411411
void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune) const;
412412

413413
/** Functions for disk access for blocks */
414-
bool ReadBlock(CBlock& block, const FlatFilePos& pos) const;
414+
bool ReadBlock(CBlock& block, const FlatFilePos& pos, const std::optional<uint256>& expected_hash = {}) const;
415415
bool ReadBlock(CBlock& block, const CBlockIndex& index) const;
416416
bool ReadRawBlock(std::vector<uint8_t>& block, const FlatFilePos& pos) const;
417417

src/test/blockmanager_tests.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,16 @@ BOOST_FIXTURE_TEST_CASE(blockmanager_block_data_availability, TestChain100Setup)
137137
BOOST_CHECK(!blockman.CheckBlockDataAvailability(tip, *last_pruned_block));
138138
}
139139

140+
BOOST_FIXTURE_TEST_CASE(blockmanager_readblock_hash_mismatch, TestingSetup)
141+
{
142+
CBlockIndex* fake_index{WITH_LOCK(m_node.chainman->GetMutex(), return m_node.chainman->ActiveChain().Tip())};
143+
fake_index->phashBlock = &uint256::ONE; // invalid block hash
144+
145+
ASSERT_DEBUG_LOG("GetHash() doesn't match index");
146+
CBlock dummy;
147+
BOOST_CHECK(!m_node.chainman->m_blockman.ReadBlock(dummy, *fake_index));
148+
}
149+
140150
BOOST_AUTO_TEST_CASE(blockmanager_flush_block_file)
141151
{
142152
KernelNotifications notifications{Assert(m_node.shutdown_request), m_node.exit_status, *Assert(m_node.warnings)};

0 commit comments

Comments
 (0)