| 5305 | } |
| 5306 | |
| 5307 | void PeerManagerImpl::EvictExtraOutboundPeers(NodeClock::time_point now) |
| 5308 | { |
| 5309 | // If we have any extra block-relay-only peers, disconnect the youngest unless |
| 5310 | // it's given us a block -- in which case, compare with the second-youngest, and |
| 5311 | // out of those two, disconnect the peer who least recently gave us a block. |
| 5312 | // The youngest block-relay-only peer would be the extra peer we connected |
| 5313 | // to temporarily in order to sync our tip; see net.cpp. |
| 5314 | // Note that we use higher nodeid as a measure for most recent connection. |
| 5315 | if (m_connman.GetExtraBlockRelayCount() > 0) { |
| 5316 | std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0}; |
| 5317 | |
| 5318 | m_connman.ForEachNode([&](CNode* pnode) { |
| 5319 | if (!pnode->IsBlockOnlyConn() || pnode->fDisconnect) return; |
| 5320 | if (pnode->GetId() > youngest_peer.first) { |
| 5321 | next_youngest_peer = youngest_peer; |
| 5322 | youngest_peer.first = pnode->GetId(); |
| 5323 | youngest_peer.second = pnode->m_last_block_time; |
| 5324 | } |
| 5325 | }); |
| 5326 | NodeId to_disconnect = youngest_peer.first; |
| 5327 | if (youngest_peer.second > next_youngest_peer.second) { |
| 5328 | // Our newest block-relay-only peer gave us a block more recently; |
| 5329 | // disconnect our second youngest. |
| 5330 | to_disconnect = next_youngest_peer.first; |
| 5331 | } |
| 5332 | m_connman.ForNode(to_disconnect, [&](CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { |
| 5333 | AssertLockHeld(::cs_main); |
| 5334 | // Make sure we're not getting a block right now, and that |
| 5335 | // we've been connected long enough for this eviction to happen |
| 5336 | // at all. |
| 5337 | // Note that we only request blocks from a peer if we learn of a |
| 5338 | // valid headers chain with at least as much work as our tip. |
| 5339 | CNodeState *node_state = State(pnode->GetId()); |
| 5340 | if (node_state == nullptr || |
| 5341 | (now - pnode->m_connected >= MINIMUM_CONNECT_TIME && node_state->vBlocksInFlight.empty())) { |
| 5342 | pnode->fDisconnect = true; |
| 5343 | LogDebug(BCLog::NET, "disconnecting extra block-relay-only peer=%d (last block received at time %d)\n", |
| 5344 | pnode->GetId(), count_seconds(pnode->m_last_block_time)); |
| 5345 | return true; |
| 5346 | } else { |
| 5347 | LogDebug(BCLog::NET, "keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n", |
| 5348 | pnode->GetId(), TicksSinceEpoch<std::chrono::seconds>(pnode->m_connected), node_state->vBlocksInFlight.size()); |
| 5349 | } |
| 5350 | return false; |
| 5351 | }); |
| 5352 | } |
| 5353 | |
| 5354 | // Check whether we have too many outbound-full-relay peers |
| 5355 | if (m_connman.GetExtraFullOutboundCount() > 0) { |
| 5356 | // If we have more outbound-full-relay peers than we target, disconnect one. |
| 5357 | // Pick the outbound-full-relay peer that least recently announced |
| 5358 | // us a new block, with ties broken by choosing the more recent |
| 5359 | // connection (higher node id) |
| 5360 | // Protect peers from eviction if we don't have another connection |
| 5361 | // to their network, counting both outbound-full-relay and manual peers. |
| 5362 | NodeId worst_peer = -1; |
| 5363 | int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max(); |
| 5364 |
nothing calls this directly
no test coverage detected