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

Code before:

    if (ppindex)
        *ppindex = pindex;

    // Since this is the earliest point at which we have determined that a
    // header is both new and valid, log here.
    //
    // These messages are valuable for detecting potential selfish mining behavior;
    // if multiple displacing headers are seen near simultaneously across many
    // nodes in the network, this might be an indication of selfish mining. Having
    // this log by default when not in IBD ensures broad availability of this data
    // in case investigation is merited.
    const auto msg = strprintf(
        "Saw new header hash=%s height=%d", hash.ToString(), pindex->nHeight);

    if (IsInitialBlockDownload()) {
        LogPrintLevel(BCLog::VALIDATION, BCLog::Level::Debug, "%s\n", msg);
    } else {
        LogPrintf("%s\n", msg);
    }

    return true;
}

// Exposed wrapper for AcceptBlockHeader
bool ChainstateManager::ProcessNewBlockHeaders(const std::span<CBlockHeader> headers, bool min_pow_checked, BlockValidationState& state, const CBlockIndex** ppindex)
{
    AssertLockNotHeld(cs_main);
    {
        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, min_pow_checked)};
            CheckBlockIndex();

            if (!accepted) {
                return false;
            }
            if (ppindex) {
                *ppindex = pindex;
            }
        }
    }
    if (NotifyHeaderTip()) {
        if (IsInitialBlockDownload() && ppindex && *ppindex) {
            const CBlockIndex& last_accepted{**ppindex};
            int64_t blocks_left{(NodeClock::now() - last_accepted.Time()) / GetConsensus().PowTargetSpacing()};
            blocks_left = std::max<int64_t>(0, blocks_left);
            const double progress{100.0 * last_accepted.nHeight / (last_accepted.nHeight + blocks_left)};
            LogInfo("Synchronizing blockheaders, height: %d (~%.2f%%)\n", last_accepted.nHeight, progress);
        }

Review comment (suggestion):
I think you want `std::span<const CBlockHeader>` for these. In addition to preserving constness, it allows elements to be passed in as `{{foo}}`, rather than specifying spans everywhere.

Code after:

    if (ppindex)
        *ppindex = pindex;

    // Since this is the earliest point at which we have determined that a
    // header is both new and valid, log here.
    //
    // These messages are valuable for detecting potential selfish mining behavior;
    // if multiple displacing headers are seen near simultaneously across many
    // nodes in the network, this might be an indication of selfish mining. Having
    // this log by default when not in IBD ensures broad availability of this data
    // in case investigation is merited.
    const auto msg = strprintf(
        "Saw new header hash=%s height=%d", hash.ToString(), pindex->nHeight);

    if (IsInitialBlockDownload()) {
        LogPrintLevel(BCLog::VALIDATION, BCLog::Level::Debug, "%s\n", msg);
    } else {
        LogPrintf("%s\n", msg);
    }

    return true;
}

// Exposed wrapper for AcceptBlockHeader
bool ChainstateManager::ProcessNewBlockHeaders(std::span<const CBlockHeader> headers, bool min_pow_checked, BlockValidationState& state, const CBlockIndex** ppindex)
{
    AssertLockNotHeld(cs_main);
    {
        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, min_pow_checked)};
            CheckBlockIndex();

            if (!accepted) {
                return false;
            }
            if (ppindex) {
                *ppindex = pindex;
            }
        }
    }
    if (NotifyHeaderTip()) {
        if (IsInitialBlockDownload() && ppindex && *ppindex) {
            const CBlockIndex& last_accepted{**ppindex};
            int64_t blocks_left{(NodeClock::now() - last_accepted.Time()) / GetConsensus().PowTargetSpacing()};
            blocks_left = std::max<int64_t>(0, blocks_left);
            const double progress{100.0 * last_accepted.nHeight / (last_accepted.nHeight + blocks_left)};
            LogInfo("Synchronizing blockheaders, height: %d (~%.2f%%)\n", last_accepted.nHeight, progress);
        }