From 0667441a7b34dde79fe0ecfc0cddc3314fa05f63 Mon Sep 17 00:00:00 2001 From: dergoegge Date: Tue, 6 Feb 2024 10:07:18 +0000 Subject: [PATCH] [validation] Cache merkle root and witness commitment checks Slight performance improvement by avoiding duplicate work. Github-Pull: #29412 Rebased-From: 1ec6bbeb8d27d31647d1433ccb87b362f6d81f90 --- src/primitives/block.h | 8 ++++++-- src/validation.cpp | 6 ++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/primitives/block.h b/src/primitives/block.h index bd11279a6e0..6117c477f81 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -71,8 +71,10 @@ public: // network and disk std::vector vtx; - // memory only - mutable bool fChecked; + // Memory-only flags for caching expensive checks + mutable bool fChecked; // CheckBlock() + mutable bool m_checked_witness_commitment{false}; // CheckWitnessCommitment() + mutable bool m_checked_merkle_root{false}; // CheckMerkleRoot() CBlock() { @@ -96,6 +98,8 @@ public: CBlockHeader::SetNull(); vtx.clear(); fChecked = false; + m_checked_witness_commitment = false; + m_checked_merkle_root = false; } CBlockHeader GetBlockHeader() const diff --git a/src/validation.cpp b/src/validation.cpp index a0e317635d4..5ef371b97b8 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3488,6 +3488,8 @@ static bool CheckBlockHeader(const CBlockHeader& block, BlockValidationState& st static bool CheckMerkleRoot(const CBlock& block, BlockValidationState& state) { + if (block.m_checked_merkle_root) return true; + bool mutated; uint256 hashMerkleRoot2 = BlockMerkleRoot(block, &mutated); if (block.hashMerkleRoot != hashMerkleRoot2) @@ -3499,12 +3501,15 @@ static bool CheckMerkleRoot(const CBlock& block, BlockValidationState& state) if (mutated) return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-txns-duplicate", "duplicate transaction"); + block.m_checked_merkle_root = true; return true; } static bool CheckWitnessMalleation(const CBlock& block, bool expect_witness_commitment, BlockValidationState& state) { if (expect_witness_commitment) { + if (block.m_checked_witness_commitment) return true; + int commitpos = GetWitnessCommitmentIndex(block); if (commitpos != NO_WITNESS_COMMITMENT) { bool malleated = false; @@ -3520,6 +3525,7 @@ static bool CheckWitnessMalleation(const CBlock& block, bool expect_witness_comm return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-witness-merkle-match", strprintf("%s : witness merkle commitment mismatch", __func__)); } + block.m_checked_witness_commitment = true; return true; } }