Repository: bitcoin/bitcoin
File: src/net_processing.cpp (C++)

Code before:
    // processing.
    if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
                chain_start_header, headers)) {
        // If we successfully started a low-work headers sync, then there
        // should be no headers to process any further.
        Assume(headers.empty());
        return;
    }

    // At this point, we have a set of headers with sufficient work on them
    // which can be processed.

    // If we don't have the last header, then this peer will have given us
    // something new (if these headers are valid).
    bool received_new_header{last_received_header == nullptr};

    // Now process all the headers.
    BlockValidationState state;
    const bool processed{m_chainman.ProcessNewBlockHeaders(headers,
                                                           /*min_pow_checked=*/true,
                                                           state, &pindexLast)};
    if (!processed) {
        if (state.IsInvalid()) {
            MaybePunishNodeForBlock(pfrom.GetId(), state, via_compact_block, "invalid header received");
            return;
        }
    }
    assert(pindexLast);

    if (processed && received_new_header) {
        LogBlockHeader(*pindexLast, pfrom, /*via_compact_block=*/false);
    }

    // Consider fetching more headers if we are not using our headers-sync mechanism.
    if (nCount == m_opts.max_headers_result && !have_headers_sync) {
        // Headers message had its maximum size; the peer may have more headers.
        if (MaybeSendGetHeaders(pfrom, GetLocator(pindexLast), peer)) {
            LogDebug(BCLog::NET, "more getheaders (%d) to end to peer=%d (startheight:%d)\n",
                    pindexLast->nHeight, pfrom.GetId(), peer.m_starting_height);
        }
    }

    UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount == m_opts.max_headers_result);

    // Consider immediately downloading blocks.
    HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);

    return;
}

std::optional<node::PackageToValidate> PeerManagerImpl::ProcessInvalidTx(NodeId nodeid, const CTransactionRef& ptx, const TxValidationState& state,

Review comment (performance):
nit to respect line-length, clang-format and grammatically make things clearer that the peer in question did not send the previous version of the header:

<details>
<summary>git diff on d55830cd50</summary>

```diff
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 073a434335..4574c6cf19 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -2957,8 +2957,10 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
     if (!processed) {
         if (state.IsInvalid()) {
             if (state.GetResult() == BlockValidationResult::BLOCK_CACHED_INVALID) {
-                LogWarning("Received header for a block previously marked as invalid from peer=%d. "
-                           "If this happens with all peers, database corruption is likely and -reindex may be necessary to recover.", pfrom.GetId());
+                LogWarning("Header received from peer=%d was previously marked as invalid. If this "
+                           "happens with all peers, database corruption is likely and restarting "
+                           "with -reindex may be necessary to recover.",
+                           pfrom.GetId());
             }
             MaybePunishNodeForBlock(pfrom.GetId(), state, via_compact_block, "invalid header received");
             return;

```
</details>


Code after:
    // processing.
    if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
                chain_start_header, headers)) {
        // If we successfully started a low-work headers sync, then there
        // should be no headers to process any further.
        Assume(headers.empty());
        return;
    }

    // At this point, we have a set of headers with sufficient work on them
    // which can be processed.

    // If we don't have the last header, then this peer will have given us
    // something new (if these headers are valid).
    bool received_new_header{last_received_header == nullptr};

    // Now process all the headers.
    BlockValidationState state;
    const bool processed{m_chainman.ProcessNewBlockHeaders(headers,
                                                           /*min_pow_checked=*/true,
                                                           state, &pindexLast)};
    if (!processed) {
        if (state.IsInvalid()) {
            if (!pfrom.IsInboundConn() && state.GetResult() == BlockValidationResult::BLOCK_CACHED_INVALID) {
                // Warn user if outgoing peers send us headers of blocks that we previously marked as invalid.
                LogWarning("%s (received from peer=%i). "
                           "If this happens with all peers, consider database corruption (that -reindex may fix) "
                           "or a potential consensus incompatibility.",
                           state.GetDebugMessage(), pfrom.GetId());
            }
            MaybePunishNodeForBlock(pfrom.GetId(), state, via_compact_block, "invalid header received");
            return;
        }
    }
    assert(pindexLast);

    if (processed && received_new_header) {
        LogBlockHeader(*pindexLast, pfrom, /*via_compact_block=*/false);
    }

    // Consider fetching more headers if we are not using our headers-sync mechanism.
    if (nCount == m_opts.max_headers_result && !have_headers_sync) {
        // Headers message had its maximum size; the peer may have more headers.
        if (MaybeSendGetHeaders(pfrom, GetLocator(pindexLast), peer)) {
            LogDebug(BCLog::NET, "more getheaders (%d) to end to peer=%d (startheight:%d)\n",
                    pindexLast->nHeight, pfrom.GetId(), peer.m_starting_height);
        }
    }

    UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount == m_opts.max_headers_result);