-
Notifications
You must be signed in to change notification settings - Fork 1.2k
perf: pass pre-computed block hash through reindex path to avoid redundant X11 computations #7272
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f7c43a2
ec87196
01e72cb
89d8c45
01af278
6e138f0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3971,18 +3971,21 @@ static bool CheckBlockHeader(const CBlockHeader& block, const uint256& hash, Blo | |
| return true; | ||
| } | ||
|
|
||
| bool CheckBlock(const CBlock& block, BlockValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW, bool fCheckMerkleRoot) | ||
| bool CheckBlock(const CBlock& block, BlockValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW, bool fCheckMerkleRoot, const uint256* known_hash) | ||
| { | ||
| // These are checks that are independent of context. | ||
|
|
||
| auto start = Now<SteadyMicroseconds>(); | ||
|
|
||
| ASSERT_IF_DEBUG(!known_hash || *known_hash == block.GetHash()); | ||
|
|
||
| if (block.fChecked) | ||
| return true; | ||
|
|
||
| // Check that the header is valid (particularly PoW). This is mostly | ||
| // redundant with the call in AcceptBlockHeader. | ||
| if (!CheckBlockHeader(block, block.GetHash(), state, consensusParams, fCheckPOW)) | ||
| const uint256 hash{known_hash ? *known_hash : block.GetHash()}; | ||
| if (!CheckBlockHeader(block, hash, state, consensusParams, fCheckPOW)) | ||
| return false; | ||
|
|
||
| // Check the merkle root. | ||
|
|
@@ -4182,11 +4185,11 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat | |
| return true; | ||
| } | ||
|
|
||
| bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationState& state, CBlockIndex** ppindex) | ||
| bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationState& state, CBlockIndex** ppindex, const uint256& hash) | ||
| { | ||
| AssertLockHeld(cs_main); | ||
| // Check for duplicate | ||
| uint256 hash = block.GetHash(); | ||
|
|
||
| ASSERT_IF_DEBUG(hash == block.GetHash()); | ||
|
|
||
| // TODO : ENABLE BLOCK CACHE IN SPECIFIC CASES | ||
| BlockMap::iterator miSelf{m_blockman.m_block_index.find(hash)}; | ||
|
|
@@ -4320,7 +4323,7 @@ bool ChainstateManager::ProcessNewBlockHeaders(const std::vector<CBlockHeader>& | |
| LOCK(cs_main); | ||
| for (const CBlockHeader& header : headers) { | ||
| CBlockIndex *pindex = nullptr; // Use a temp pindex instead of ppindex to avoid a const_cast | ||
| bool accepted{AcceptBlockHeader(header, state, &pindex)}; | ||
| bool accepted{AcceptBlockHeader(header, state, &pindex, header.GetHash())}; | ||
| ActiveChainstate().CheckBlockIndex(); | ||
|
|
||
| if (!accepted) { | ||
|
|
@@ -4343,7 +4346,7 @@ bool ChainstateManager::ProcessNewBlockHeaders(const std::vector<CBlockHeader>& | |
| } | ||
|
|
||
| /** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */ | ||
| bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockValidationState& state, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock) | ||
| bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockValidationState& state, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock, const uint256* known_hash) | ||
| { | ||
| auto start = Now<SteadyMicroseconds>(); | ||
|
|
||
|
|
@@ -4355,7 +4358,13 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, Block | |
| CBlockIndex *pindexDummy = nullptr; | ||
| CBlockIndex *&pindex = ppindex ? *ppindex : pindexDummy; | ||
|
|
||
| bool accepted_header{m_chainman.AcceptBlockHeader(block, state, &pindex)}; | ||
| // If the caller supplies a pre-computed hash, verify it in debug builds. | ||
| // In release builds a wrong hash is still caught: AcceptBlockHeader calls | ||
| // CheckBlockHeader which runs CheckProofOfWork against the header's nBits. | ||
| ASSERT_IF_DEBUG(!known_hash || *known_hash == block.GetHash()); | ||
|
|
||
| const uint256 hash{known_hash ? *known_hash : block.GetHash()}; | ||
| bool accepted_header{m_chainman.AcceptBlockHeader(block, state, &pindex, hash)}; | ||
|
Comment on lines
+4364
to
+4367
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Suggestion: known_hash correctness relies on implicit PoW guard rather than explicit validation
However, this is not unguarded in practice: The residual concern is that this protection is incidental rather than documented. If a future change introduced a source: ['claude', 'codex'] 🤖 Fix this with AI agents |
||
| CheckBlockIndex(); | ||
|
|
||
| if (!accepted_header) | ||
|
|
@@ -4394,7 +4403,7 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, Block | |
| if (pindex->nChainWork < nMinimumChainWork) return true; | ||
| } | ||
|
|
||
| if (!CheckBlock(block, state, m_params.GetConsensus()) || | ||
| if (!CheckBlock(block, state, m_params.GetConsensus(), true, true, &hash) || | ||
| !ContextualCheckBlock(block, state, m_chainman, pindex->pprev)) { | ||
| if (state.IsInvalid() && state.GetResult() != BlockValidationResult::BLOCK_MUTATED) { | ||
| pindex->nStatus |= BLOCK_FAILED_VALID; | ||
|
|
@@ -5146,7 +5155,7 @@ void CChainState::LoadExternalBlockFile( | |
| nRewind = blkdat.GetPos(); | ||
|
|
||
| BlockValidationState state; | ||
| if (AcceptBlock(pblock, state, nullptr, true, dbp, nullptr)) { | ||
| if (AcceptBlock(pblock, state, nullptr, true, dbp, nullptr, &hash)) { | ||
| nLoaded++; | ||
| } | ||
| if (state.IsError()) { | ||
|
|
@@ -5179,14 +5188,15 @@ void CChainState::LoadExternalBlockFile( | |
| while (range.first != range.second) { | ||
| std::multimap<uint256, FlatFilePos>::iterator it = range.first; | ||
| std::shared_ptr<CBlock> pblockrecursive = std::make_shared<CBlock>(); | ||
| if (ReadBlockFromDisk(*pblockrecursive, it->second, m_params.GetConsensus())) { | ||
| LogPrint(BCLog::REINDEX, "%s: Processing out of order child %s of %s\n", __func__, pblockrecursive->GetHash().ToString(), | ||
| if (auto opt_hash{ReadBlockFromDisk(*pblockrecursive, it->second, m_params.GetConsensus())}) { | ||
| const uint256& blockhash = *opt_hash; | ||
| LogPrint(BCLog::REINDEX, "%s: Processing out of order child %s of %s\n", __func__, blockhash.ToString(), | ||
| head.ToString()); | ||
| LOCK(cs_main); | ||
| BlockValidationState dummy; | ||
| if (AcceptBlock(pblockrecursive, dummy, nullptr, true, &it->second, nullptr)) { | ||
| if (AcceptBlock(pblockrecursive, dummy, nullptr, true, &it->second, nullptr, &blockhash)) { | ||
| nLoaded++; | ||
| queue.push_back(pblockrecursive->GetHash()); | ||
| queue.push_back(blockhash); | ||
| } | ||
| } | ||
| range.first++; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.