| 5245 | } |
| 5246 | |
| 5247 | void PeerManagerImpl::ConsiderEviction(CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds) |
| 5248 | { |
| 5249 | AssertLockHeld(cs_main); |
| 5250 | |
| 5251 | CNodeState &state = *State(pto.GetId()); |
| 5252 | |
| 5253 | if (!state.m_chain_sync.m_protect && pto.IsOutboundOrBlockRelayConn() && state.fSyncStarted) { |
| 5254 | // This is an outbound peer subject to disconnection if they don't |
| 5255 | // announce a block with as much work as the current tip within |
| 5256 | // CHAIN_SYNC_TIMEOUT + HEADERS_RESPONSE_TIME seconds (note: if |
| 5257 | // their chain has more work than ours, we should sync to it, |
| 5258 | // unless it's invalid, in which case we should find that out and |
| 5259 | // disconnect from them elsewhere). |
| 5260 | if (state.pindexBestKnownBlock != nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.ActiveChain().Tip()->nChainWork) { |
| 5261 | // The outbound peer has sent us a block with at least as much work as our current tip, so reset the timeout if it was set |
| 5262 | if (state.m_chain_sync.m_timeout != 0s) { |
| 5263 | state.m_chain_sync.m_timeout = 0s; |
| 5264 | state.m_chain_sync.m_work_header = nullptr; |
| 5265 | state.m_chain_sync.m_sent_getheaders = false; |
| 5266 | } |
| 5267 | } else if (state.m_chain_sync.m_timeout == 0s || (state.m_chain_sync.m_work_header != nullptr && state.pindexBestKnownBlock != nullptr && state.pindexBestKnownBlock->nChainWork >= state.m_chain_sync.m_work_header->nChainWork)) { |
| 5268 | // At this point we know that the outbound peer has either never sent us a block/header or they have, but its tip is behind ours |
| 5269 | // AND |
| 5270 | // we are noticing this for the first time (m_timeout is 0) |
| 5271 | // OR we noticed this at some point within the last CHAIN_SYNC_TIMEOUT + HEADERS_RESPONSE_TIME seconds and set a timeout |
| 5272 | // for them, they caught up to our tip at the time of setting the timer but not to our current one (we've also advanced). |
| 5273 | // Either way, set a new timeout based on our current tip. |
| 5274 | state.m_chain_sync.m_timeout = time_in_seconds + CHAIN_SYNC_TIMEOUT; |
| 5275 | state.m_chain_sync.m_work_header = m_chainman.ActiveChain().Tip(); |
| 5276 | state.m_chain_sync.m_sent_getheaders = false; |
| 5277 | } else if (state.m_chain_sync.m_timeout > 0s && time_in_seconds > state.m_chain_sync.m_timeout) { |
| 5278 | // No evidence yet that our peer has synced to a chain with work equal to that |
| 5279 | // of our tip, when we first detected it was behind. Send a single getheaders |
| 5280 | // message to give the peer a chance to update us. |
| 5281 | if (state.m_chain_sync.m_sent_getheaders) { |
| 5282 | // They've run out of time to catch up! |
| 5283 | LogInfo("Outbound peer has old chain, best known block = %s, %s", state.pindexBestKnownBlock != nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() : "<none>", pto.DisconnectMsg()); |
| 5284 | pto.fDisconnect = true; |
| 5285 | } else { |
| 5286 | assert(state.m_chain_sync.m_work_header); |
| 5287 | // Here, we assume that the getheaders message goes out, |
| 5288 | // because it'll either go out or be skipped because of a |
| 5289 | // getheaders in-flight already, in which case the peer should |
| 5290 | // still respond to us with a sufficiently high work chain tip. |
| 5291 | MaybeSendGetHeaders(pto, |
| 5292 | GetLocator(state.m_chain_sync.m_work_header->pprev), |
| 5293 | peer); |
| 5294 | LogDebug(BCLog::NET, "sending getheaders to outbound peer=%d to verify chain work (current best known block:%s, benchmark blockhash: %s)\n", pto.GetId(), state.pindexBestKnownBlock != nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() : "<none>", state.m_chain_sync.m_work_header->GetBlockHash().ToString()); |
| 5295 | state.m_chain_sync.m_sent_getheaders = true; |
| 5296 | // Bump the timeout to allow a response, which could clear the timeout |
| 5297 | // (if the response shows the peer has synced), reset the timeout (if |
| 5298 | // the peer syncs to the required work but not to our tip), or result |
| 5299 | // in disconnect (if we advance to the timeout and pindexBestKnownBlock |
| 5300 | // has not sufficiently progressed) |
| 5301 | state.m_chain_sync.m_timeout = time_in_seconds + HEADERS_RESPONSE_TIME; |
| 5302 | } |
| 5303 | } |
| 5304 | } |
nothing calls this directly
no test coverage detected