refactor: Compute work from headers without CBlockIndex

Avoid the need to construct a CBlockIndex object just to compute work for a header,
when its nBits value suffices for that.

Co-Authored-By: Pieter Wuille <pieter@wuille.net>
This commit is contained in:
Daniela BrozzoniandPieter Wuille committed 2025-11-03 03:52:11 +01:00
1 parent 0bf6139e19
commit 4066bfe561
5 files changed
+16 -9

No files matched your search

+2 -2
View File
@@ -124,12 +124,12 @@ void CBlockIndex::BuildSkip()
pskip = pprev->GetAncestor(GetSkipHeight(nHeight)); pskip = pprev->GetAncestor(GetSkipHeight(nHeight));
} }
arith_uint256 GetBlockProof(const CBlockIndex& block) arith_uint256 GetBitsProof(uint32_t bits)
{ {
arith_uint256 bnTarget; arith_uint256 bnTarget;
bool fNegative; bool fNegative;
bool fOverflow; bool fOverflow;
bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow); bnTarget.SetCompact(bits, &fNegative, &fOverflow);
if (fNegative || fOverflow || bnTarget == 0) if (fNegative || fOverflow || bnTarget == 0)
return 0; return 0;
// We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256 // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256
+9 -1
View File
@@ -348,7 +348,15 @@ protected:
CBlockIndex& operator=(CBlockIndex&&) = delete; CBlockIndex& operator=(CBlockIndex&&) = delete;
}; };
arith_uint256 GetBlockProof(const CBlockIndex& block); /** Compute how much work an nBits value corresponds to. */
arith_uint256 GetBitsProof(uint32_t bits);
/** Compute how much work a block index entry corresponds to. */
inline arith_uint256 GetBlockProof(const CBlockIndex& block) { return GetBitsProof(block.nBits); }
/** Compute how much work a block header corresponds to. */
inline arith_uint256 GetBlockProof(const CBlockHeader& header) { return GetBitsProof(header.nBits); }
/** Return the time it would take to redo the work difference between from and to, assuming the current hashrate corresponds to the difficulty at tip, in seconds. */ /** Return the time it would take to redo the work difference between from and to, assuming the current hashrate corresponds to the difficulty at tip, in seconds. */
int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params&); int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params&);
/** Find the forking point between two chain tips. */ /** Find the forking point between two chain tips. */
+2 -2
View File
@@ -202,7 +202,7 @@ bool HeadersSyncState::ValidateAndProcessSingleHeader(const CBlockHeader& curren
} }
} }
m_current_chain_work += GetBlockProof(CBlockIndex(current)); m_current_chain_work += GetBlockProof(current);
m_last_header_received = current; m_last_header_received = current;
m_current_height = next_height; m_current_height = next_height;
@@ -238,7 +238,7 @@ bool HeadersSyncState::ValidateAndStoreRedownloadedHeader(const CBlockHeader& he
} }
// Track work on the redownloaded chain // Track work on the redownloaded chain
m_redownload_chain_work += GetBlockProof(CBlockIndex(header)); m_redownload_chain_work += GetBlockProof(header);
if (m_redownload_chain_work >= m_minimum_required_work) { if (m_redownload_chain_work >= m_minimum_required_work) {
m_process_all_remaining_headers = true; m_process_all_remaining_headers = true;
+2 -2
View File
@@ -4348,7 +4348,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
MaybeSendGetHeaders(pfrom, GetLocator(m_chainman.m_best_header), *peer); MaybeSendGetHeaders(pfrom, GetLocator(m_chainman.m_best_header), *peer);
} }
return; return;
} else if (prev_block->nChainWork + CalculateClaimedHeadersWork({{cmpctblock.header}}) < GetAntiDoSWorkThreshold()) { } else if (prev_block->nChainWork + GetBlockProof(cmpctblock.header) < GetAntiDoSWorkThreshold()) {
// If we get a low-work header in a compact block, we can ignore it. // If we get a low-work header in a compact block, we can ignore it.
LogDebug(BCLog::NET, "Ignoring low-work compact block from peer %d\n", pfrom.GetId()); LogDebug(BCLog::NET, "Ignoring low-work compact block from peer %d\n", pfrom.GetId());
return; return;
@@ -4666,7 +4666,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
mapBlockSource.emplace(hash, std::make_pair(pfrom.GetId(), true)); mapBlockSource.emplace(hash, std::make_pair(pfrom.GetId(), true));
// Check claimed work on this block against our anti-dos thresholds. // Check claimed work on this block against our anti-dos thresholds.
if (prev_block && prev_block->nChainWork + CalculateClaimedHeadersWork({{pblock->GetBlockHeader()}}) >= GetAntiDoSWorkThreshold()) { if (prev_block && prev_block->nChainWork + GetBlockProof(pblock->GetBlockHeader()) >= GetAntiDoSWorkThreshold()) {
min_pow_checked = true; min_pow_checked = true;
} }
} }
+1 -2
View File
@@ -4171,8 +4171,7 @@ arith_uint256 CalculateClaimedHeadersWork(std::span<const CBlockHeader> headers)
{ {
arith_uint256 total_work{0}; arith_uint256 total_work{0};
for (const CBlockHeader& header : headers) { for (const CBlockHeader& header : headers) {
CBlockIndex dummy(header); total_work += GetBlockProof(header);
total_work += GetBlockProof(dummy);
} }
return total_work; return total_work;
} }