| 4272 | } |
| 4273 | |
| 4274 | void PeerManagerImpl::ConsiderEviction(CNode& pto, std::chrono::seconds time_in_seconds) |
| 4275 | { |
| 4276 | AssertLockHeld(cs_main); |
| 4277 | |
| 4278 | CNodeState &state = *State(pto.GetId()); |
| 4279 | const CNetMsgMaker msgMaker(pto.GetCommonVersion()); |
| 4280 | |
| 4281 | if (!state.m_chain_sync.m_protect && pto.IsOutboundOrBlockRelayConn() && state.fSyncStarted) { |
| 4282 | // This is an outbound peer subject to disconnection if they don't |
| 4283 | // announce a block with as much work as the current tip within |
| 4284 | // CHAIN_SYNC_TIMEOUT + HEADERS_RESPONSE_TIME seconds (note: if |
| 4285 | // their chain has more work than ours, we should sync to it, |
| 4286 | // unless it's invalid, in which case we should find that out and |
| 4287 | // disconnect from them elsewhere). |
| 4288 | if (state.pindexBestKnownBlock != nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.ActiveChain().Tip()->nChainWork) { |
| 4289 | if (state.m_chain_sync.m_timeout != 0s) { |
| 4290 | state.m_chain_sync.m_timeout = 0s; |
| 4291 | state.m_chain_sync.m_work_header = nullptr; |
| 4292 | state.m_chain_sync.m_sent_getheaders = false; |
| 4293 | } |
| 4294 | } 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)) { |
| 4295 | // Our best block known by this peer is behind our tip, and we're either noticing |
| 4296 | // that for the first time, OR this peer was able to catch up to some earlier point |
| 4297 | // where we checked against our tip. |
| 4298 | // Either way, set a new timeout based on current tip. |
| 4299 | state.m_chain_sync.m_timeout = time_in_seconds + CHAIN_SYNC_TIMEOUT; |
| 4300 | state.m_chain_sync.m_work_header = m_chainman.ActiveChain().Tip(); |
| 4301 | state.m_chain_sync.m_sent_getheaders = false; |
| 4302 | } else if (state.m_chain_sync.m_timeout > 0s && time_in_seconds > state.m_chain_sync.m_timeout) { |
| 4303 | // No evidence yet that our peer has synced to a chain with work equal to that |
| 4304 | // of our tip, when we first detected it was behind. Send a single getheaders |
| 4305 | // message to give the peer a chance to update us. |
| 4306 | if (state.m_chain_sync.m_sent_getheaders) { |
| 4307 | // They've run out of time to catch up! |
| 4308 | LogPrintf("Disconnecting outbound peer %d for old chain, best known block = %s\n", pto.GetId(), state.pindexBestKnownBlock != nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() : "<none>"); |
| 4309 | pto.fDisconnect = true; |
| 4310 | } else { |
| 4311 | assert(state.m_chain_sync.m_work_header); |
| 4312 | LogPrint(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()); |
| 4313 | m_connman.PushMessage(&pto, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(state.m_chain_sync.m_work_header->pprev), uint256())); |
| 4314 | state.m_chain_sync.m_sent_getheaders = true; |
| 4315 | constexpr auto HEADERS_RESPONSE_TIME{2min}; |
| 4316 | // Bump the timeout to allow a response, which could clear the timeout |
| 4317 | // (if the response shows the peer has synced), reset the timeout (if |
| 4318 | // the peer syncs to the required work but not to our tip), or result |
| 4319 | // in disconnect (if we advance to the timeout and pindexBestKnownBlock |
| 4320 | // has not sufficiently progressed) |
| 4321 | state.m_chain_sync.m_timeout = time_in_seconds + HEADERS_RESPONSE_TIME; |
| 4322 | } |
| 4323 | } |
| 4324 | } |
| 4325 | } |
| 4326 | |
| 4327 | void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now) |
| 4328 | { |
nothing calls this directly
no test coverage detected