Skip to content

Commit cb5b222

Browse files
committed
validation: Return BlockValidationState from ProcessNewBlockHeaders
Return BlockValidationState by value instead of using an out-parameter, similar to the TestBlockValidity refactoring in 74690f4. This provides a cleaner API and enables callers to inspect detailed validation state without relying on side effects through reference parameters.
1 parent 8cfc6a8 commit cb5b222

File tree

7 files changed

+38
-41
lines changed

7 files changed

+38
-41
lines changed

src/net_processing.cpp

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3046,27 +3046,24 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
30463046
// something new (if these headers are valid).
30473047
bool received_new_header{last_received_header == nullptr};
30483048

3049-
// Now process all the headers.
3050-
BlockValidationState state;
3051-
const bool processed{m_chainman.ProcessNewBlockHeaders(headers,
3049+
// Now process all the headers and return the block validation state.
3050+
BlockValidationState state{m_chainman.ProcessNewBlockHeaders(headers,
30523051
/*min_pow_checked=*/true,
3053-
state, &pindexLast)};
3054-
if (!processed) {
3055-
if (state.IsInvalid()) {
3056-
if (!pfrom.IsInboundConn() && state.GetResult() == BlockValidationResult::BLOCK_CACHED_INVALID) {
3057-
// Warn user if outgoing peers send us headers of blocks that we previously marked as invalid.
3058-
LogWarning("%s (received from peer=%i). "
3059-
"If this happens with all peers, consider database corruption (that -reindex may fix) "
3060-
"or a potential consensus incompatibility.",
3061-
state.GetDebugMessage(), pfrom.GetId());
3062-
}
3063-
MaybePunishNodeForBlock(pfrom.GetId(), state, via_compact_block, "invalid header received");
3064-
return;
3065-
}
3052+
&pindexLast)};
3053+
if (state.IsInvalid()) {
3054+
if (!pfrom.IsInboundConn() && state.GetResult() == BlockValidationResult::BLOCK_CACHED_INVALID) {
3055+
// Warn user if outgoing peers send us headers of blocks that we previously marked as invalid.
3056+
LogWarning("%s (received from peer=%i). "
3057+
"If this happens with all peers, consider database corruption (that -reindex may fix) "
3058+
"or a potential consensus incompatibility.",
3059+
state.GetDebugMessage(), pfrom.GetId());
3060+
}
3061+
MaybePunishNodeForBlock(pfrom.GetId(), state, via_compact_block, "invalid header received");
3062+
return;
30663063
}
30673064
assert(pindexLast);
30683065

3069-
if (processed && received_new_header) {
3066+
if (state.IsValid() && received_new_header) {
30703067
LogBlockHeader(*pindexLast, pfrom, /*via_compact_block=*/false);
30713068
}
30723069

@@ -4558,12 +4555,10 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
45584555
}
45594556

45604557
const CBlockIndex *pindex = nullptr;
4561-
BlockValidationState state;
4562-
if (!m_chainman.ProcessNewBlockHeaders({{cmpctblock.header}}, /*min_pow_checked=*/true, state, &pindex)) {
4563-
if (state.IsInvalid()) {
4564-
MaybePunishNodeForBlock(pfrom.GetId(), state, /*via_compact_block=*/true, "invalid header via cmpctblock");
4565-
return;
4566-
}
4558+
BlockValidationState state{m_chainman.ProcessNewBlockHeaders({{cmpctblock.header}}, /*min_pow_checked=*/true, &pindex)};
4559+
if (state.IsInvalid()) {
4560+
MaybePunishNodeForBlock(pfrom.GetId(), state, /*via_compact_block=*/true, "invalid header via cmpctblock");
4561+
return;
45674562
}
45684563

45694564
// If AcceptBlockHeader returned true, it set pindex

src/rpc/mining.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,8 +1123,7 @@ static RPCHelpMan submitheader()
11231123
}
11241124
}
11251125

1126-
BlockValidationState state;
1127-
chainman.ProcessNewBlockHeaders({{h}}, /*min_pow_checked=*/true, state);
1126+
BlockValidationState state{chainman.ProcessNewBlockHeaders({{h}}, /*min_pow_checked=*/true)};
11281127
if (state.IsValid()) return UniValue::VNULL;
11291128
if (state.IsError()) {
11301129
throw JSONRPCError(RPC_VERIFY_ERROR, state.ToString());

src/test/blockfilter_index_tests.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,7 @@ bool BuildChainTestingSetup::BuildChain(const CBlockIndex* pindex,
103103
for (auto& block : chain) {
104104
block = std::make_shared<CBlock>(CreateBlock(pindex, no_txns, coinbase_script_pub_key));
105105

106-
BlockValidationState state;
107-
if (!Assert(m_node.chainman)->ProcessNewBlockHeaders({{*block}}, true, state, &pindex)) {
106+
if (!Assert(m_node.chainman)->ProcessNewBlockHeaders({{*block}}, true, &pindex).IsValid()) {
108107
return false;
109108
}
110109
}

src/test/fuzz/utxo_snapshot.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,8 @@ void initialize_chain()
8888
if constexpr (INVALID) {
8989
auto& chainman{*setup->m_node.chainman};
9090
for (const auto& block : chain) {
91-
BlockValidationState dummy;
92-
bool processed{chainman.ProcessNewBlockHeaders({{*block}}, true, dummy)};
93-
Assert(processed);
91+
auto result{chainman.ProcessNewBlockHeaders({{*block}}, true)};
92+
Assert(result.IsValid());
9493
const auto* index{WITH_LOCK(::cs_main, return chainman.m_blockman.LookupBlockIndex(block->GetHash()))};
9594
Assert(index);
9695
}
@@ -170,9 +169,8 @@ void utxo_snapshot_fuzz(FuzzBufferType buffer)
170169
// Consume the bool, but skip the code for the INVALID fuzz target
171170
if constexpr (!INVALID) {
172171
for (const auto& block : *g_chain) {
173-
BlockValidationState dummy;
174-
bool processed{chainman.ProcessNewBlockHeaders({{*block}}, true, dummy)};
175-
Assert(processed);
172+
auto result{chainman.ProcessNewBlockHeaders({{*block}}, true)};
173+
Assert(result.IsValid());
176174
const auto* index{WITH_LOCK(::cs_main, return chainman.m_blockman.LookupBlockIndex(block->GetHash()))};
177175
Assert(index);
178176
}

src/test/validation_block_tests.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,7 @@ std::shared_ptr<CBlock> MinerTestingSetup::FinalizeBlock(std::shared_ptr<CBlock>
104104

105105
// submit block header, so that miner can get the block height from the
106106
// global state and the node has the topology of the chain
107-
BlockValidationState ignored;
108-
BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlockHeaders({{*pblock}}, true, ignored));
107+
BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlockHeaders({{*pblock}}, true).IsValid());
109108

110109
return pblock;
111110
}

src/validation.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4300,9 +4300,11 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida
43004300
}
43014301

43024302
// Exposed wrapper for AcceptBlockHeader
4303-
bool ChainstateManager::ProcessNewBlockHeaders(std::span<const CBlockHeader> headers, bool min_pow_checked, BlockValidationState& state, const CBlockIndex** ppindex)
4303+
BlockValidationState ChainstateManager::ProcessNewBlockHeaders(std::span<const CBlockHeader> headers, bool min_pow_checked, const CBlockIndex** ppindex)
43044304
{
43054305
AssertLockNotHeld(cs_main);
4306+
Assume(!headers.empty());
4307+
BlockValidationState state;
43064308
{
43074309
LOCK(cs_main);
43084310
for (const CBlockHeader& header : headers) {
@@ -4311,8 +4313,10 @@ bool ChainstateManager::ProcessNewBlockHeaders(std::span<const CBlockHeader> hea
43114313
CheckBlockIndex();
43124314

43134315
if (!accepted) {
4314-
return false;
4316+
if (state.IsValid()) NONFATAL_UNREACHABLE();
4317+
return state;
43154318
}
4319+
43164320
if (ppindex) {
43174321
*ppindex = pindex;
43184322
}
@@ -4327,7 +4331,9 @@ bool ChainstateManager::ProcessNewBlockHeaders(std::span<const CBlockHeader> hea
43274331
LogInfo("Synchronizing blockheaders, height: %d (~%.2f%%)\n", last_accepted.nHeight, progress);
43284332
}
43294333
}
4330-
return true;
4334+
4335+
if (!state.IsValid()) NONFATAL_UNREACHABLE();
4336+
return state;
43314337
}
43324338

43334339
void ChainstateManager::ReportHeadersPresync(int64_t height, int64_t timestamp)

src/validation.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,11 +1239,12 @@ class ChainstateManager
12391239
*
12401240
* @param[in] headers The block headers themselves
12411241
* @param[in] min_pow_checked True if proof-of-work anti-DoS checks have been done by caller for headers chain
1242-
* @param[out] state This may be set to an Error state if any error occurred processing them
12431242
* @param[out] ppindex If set, the pointer will be set to point to the last new block index object for the given headers
1244-
* @returns false if AcceptBlockHeader fails on any of the headers, true otherwise (including if headers were already known)
1243+
* @returns BlockValidationState indicating the result. IsValid() returns true if all headers
1244+
* were accepted. On failure, IsInvalid() is true and the state contains the specific
1245+
* validation failure reason.
12451246
*/
1246-
bool ProcessNewBlockHeaders(std::span<const CBlockHeader> headers, bool min_pow_checked, BlockValidationState& state, const CBlockIndex** ppindex = nullptr) LOCKS_EXCLUDED(cs_main);
1247+
BlockValidationState ProcessNewBlockHeaders(std::span<const CBlockHeader> headers, bool min_pow_checked, const CBlockIndex** ppindex = nullptr) LOCKS_EXCLUDED(cs_main);
12471248

12481249
/**
12491250
* Sufficiently validate a block for disk storage (and store on disk).

0 commit comments

Comments
 (0)