| 2711 | } |
| 2712 | |
| 2713 | bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer, CNode& pfrom, std::vector<CBlockHeader>& headers) |
| 2714 | { |
| 2715 | if (peer.m_headers_sync) { |
| 2716 | auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() == m_opts.max_headers_result); |
| 2717 | // If it is a valid continuation, we should treat the existing getheaders request as responded to. |
| 2718 | if (result.success) peer.m_last_getheaders_timestamp = {}; |
| 2719 | if (result.request_more) { |
| 2720 | auto locator = peer.m_headers_sync->NextHeadersRequestLocator(); |
| 2721 | // If we were instructed to ask for a locator, it should not be empty. |
| 2722 | Assume(!locator.vHave.empty()); |
| 2723 | // We can only be instructed to request more if processing was successful. |
| 2724 | Assume(result.success); |
| 2725 | if (!locator.vHave.empty()) { |
| 2726 | // It should be impossible for the getheaders request to fail, |
| 2727 | // because we just cleared the last getheaders timestamp. |
| 2728 | bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer); |
| 2729 | Assume(sent_getheaders); |
| 2730 | LogDebug(BCLog::NET, "more getheaders (from %s) to peer=%d\n", |
| 2731 | locator.vHave.front().ToString(), pfrom.GetId()); |
| 2732 | } |
| 2733 | } |
| 2734 | |
| 2735 | if (peer.m_headers_sync->GetState() == HeadersSyncState::State::FINAL) { |
| 2736 | peer.m_headers_sync.reset(nullptr); |
| 2737 | |
| 2738 | // Delete this peer's entry in m_headers_presync_stats. |
| 2739 | // If this is m_headers_presync_bestpeer, it will be replaced later |
| 2740 | // by the next peer that triggers the else{} branch below. |
| 2741 | LOCK(m_headers_presync_mutex); |
| 2742 | m_headers_presync_stats.erase(pfrom.GetId()); |
| 2743 | } else { |
| 2744 | // Build statistics for this peer's sync. |
| 2745 | HeadersPresyncStats stats; |
| 2746 | stats.first = peer.m_headers_sync->GetPresyncWork(); |
| 2747 | if (peer.m_headers_sync->GetState() == HeadersSyncState::State::PRESYNC) { |
| 2748 | stats.second = {peer.m_headers_sync->GetPresyncHeight(), |
| 2749 | peer.m_headers_sync->GetPresyncTime()}; |
| 2750 | } |
| 2751 | |
| 2752 | // Update statistics in stats. |
| 2753 | LOCK(m_headers_presync_mutex); |
| 2754 | m_headers_presync_stats[pfrom.GetId()] = stats; |
| 2755 | auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer); |
| 2756 | bool best_updated = false; |
| 2757 | if (best_it == m_headers_presync_stats.end()) { |
| 2758 | // If the cached best peer is outdated, iterate over all remaining ones (including |
| 2759 | // newly updated one) to find the best one. |
| 2760 | NodeId peer_best{-1}; |
| 2761 | const HeadersPresyncStats* stat_best{nullptr}; |
| 2762 | for (const auto& [peer, stat] : m_headers_presync_stats) { |
| 2763 | if (!stat_best || stat > *stat_best) { |
| 2764 | peer_best = peer; |
| 2765 | stat_best = &stat; |
| 2766 | } |
| 2767 | } |
| 2768 | m_headers_presync_bestpeer = peer_best; |
| 2769 | best_updated = (peer_best == pfrom.GetId()); |
| 2770 | } else if (best_it->first == pfrom.GetId() || stats > best_it->second) { |
nothing calls this directly
no test coverage detected