| 2083 | } |
| 2084 | |
| 2085 | void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer, |
| 2086 | const std::vector<CBlockHeader>& headers, |
| 2087 | bool via_compact_block) |
| 2088 | { |
| 2089 | const CNetMsgMaker msgMaker(pfrom.GetCommonVersion()); |
| 2090 | size_t nCount = headers.size(); |
| 2091 | |
| 2092 | if (nCount == 0) { |
| 2093 | // Nothing interesting. Stop asking this peers for more headers. |
| 2094 | return; |
| 2095 | } |
| 2096 | |
| 2097 | // If we are already too far ahead of where we want to be on headers, discard |
| 2098 | // the received headers. We can still get ahead by up to a single maximum-sized |
| 2099 | // headers message here, but never further, so that's fine. |
| 2100 | if (node::fTrimHeaders) { |
| 2101 | LOCK(cs_main); |
| 2102 | if (pindexBestHeader) { |
| 2103 | int64_t headers_ahead = pindexBestHeader->nHeight - m_chainman.ActiveHeight(); |
| 2104 | if (headers_ahead >= node::nHeaderDownloadBuffer) { |
| 2105 | CNodeState *nodestate = State(pfrom.GetId()); |
| 2106 | if ((nodestate->pindexBestKnownBlock == nullptr) || |
| 2107 | (nodestate->pindexBestKnownBlock->nHeight < m_chainman.ActiveHeight())) { |
| 2108 | // Our notion of what blocks a peer has available is based on its pindexBestKnownBlock, |
| 2109 | // which is based on headers received from it. If we don't have one, or it's too old, |
| 2110 | // then we can never get blocks from this peer until we accept headers from it first. |
| 2111 | LogPrint(BCLog::NET, "NOT discarding headers from peer=%d, to update its block availability. (current best header %d, active chain height %d)\n", pfrom.GetId(), pindexBestHeader->nHeight, m_chainman.ActiveHeight()); |
| 2112 | } else { |
| 2113 | LogPrint(BCLog::NET, "Discarding received headers and pausing header sync from peer=%d, because we are too far ahead of block sync. (%d > %d)\n", pfrom.GetId(), pindexBestHeader->nHeight, m_chainman.ActiveHeight()); |
| 2114 | if (nodestate->fSyncStarted) { |
| 2115 | // Cancel sync from this node, so we don't penalize it later. |
| 2116 | // This will cause us to automatically start syncing from a different node (or restart syncing from the same node) later, |
| 2117 | // if we still need to sync headers. |
| 2118 | nSyncStarted--; |
| 2119 | nodestate->fSyncStarted = false; |
| 2120 | nodestate->m_headers_sync_timeout = 0us; |
| 2121 | } |
| 2122 | return; |
| 2123 | } |
| 2124 | } |
| 2125 | } |
| 2126 | } |
| 2127 | |
| 2128 | bool received_new_header = false; |
| 2129 | const CBlockIndex *pindexLast = nullptr; |
| 2130 | { |
| 2131 | LOCK(cs_main); |
| 2132 | CNodeState *nodestate = State(pfrom.GetId()); |
| 2133 | |
| 2134 | // If this looks like it could be a block announcement (nCount < |
| 2135 | // MAX_BLOCKS_TO_ANNOUNCE), use special logic for handling headers that |
| 2136 | // don't connect: |
| 2137 | // - Send a getheaders message in response to try to connect the chain. |
| 2138 | // - The peer can send up to MAX_UNCONNECTING_HEADERS in a row that |
| 2139 | // don't connect before giving DoS points |
| 2140 | // - Once a headers message is received that is valid and does connect, |
| 2141 | // nUnconnectingHeaders gets reset back to 0. |
| 2142 | if (!m_chainman.m_blockman.LookupBlockIndex(headers[0].hashPrevBlock) && nCount < MAX_BLOCKS_TO_ANNOUNCE) { |
nothing calls this directly
no test coverage detected