Merge #7974: More comments on the design of AttemptToEvictConnection.

d90351f More comments on the design of AttemptToEvictConnection. (Gregory Maxwell)
This commit is contained in:
Wladimir J. van der Laan 2016-05-04 15:51:38 +02:00
commit 8206835cc1
No known key found for this signature in database
GPG key ID: 74810B012346C9A6

View file

@ -877,6 +877,14 @@ public:
} }
}; };
/** Try to find a connection to evict when the node is full.
* Extreme care must be taken to avoid opening the node to attacker
* triggered network partitioning.
* The strategy used here is to protect a small number of peers
* for each of several distinct characteristics which are difficult
* to forge. In order to partition a node the attacker must be
* simultaneously better at all of them than honest peers.
*/
static bool AttemptToEvictConnection(bool fPreferNewConnection) { static bool AttemptToEvictConnection(bool fPreferNewConnection) {
std::vector<CNodeRef> vEvictionCandidates; std::vector<CNodeRef> vEvictionCandidates;
{ {
@ -905,7 +913,7 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
if (vEvictionCandidates.empty()) return false; if (vEvictionCandidates.empty()) return false;
// Protect the 8 nodes with the best ping times. // Protect the 8 nodes with the lowest minimum ping time.
// An attacker cannot manipulate this metric without physically moving nodes closer to the target. // An attacker cannot manipulate this metric without physically moving nodes closer to the target.
std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), ReverseCompareNodeMinPingTime); std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), ReverseCompareNodeMinPingTime);
vEvictionCandidates.erase(vEvictionCandidates.end() - std::min(8, static_cast<int>(vEvictionCandidates.size())), vEvictionCandidates.end()); vEvictionCandidates.erase(vEvictionCandidates.end() - std::min(8, static_cast<int>(vEvictionCandidates.size())), vEvictionCandidates.end());
@ -913,7 +921,7 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
if (vEvictionCandidates.empty()) return false; if (vEvictionCandidates.empty()) return false;
// Protect the half of the remaining nodes which have been connected the longest. // Protect the half of the remaining nodes which have been connected the longest.
// This replicates the existing implicit behavior. // This replicates the non-eviction implicit behavior, and precludes attacks that start later.
std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), ReverseCompareNodeTimeConnected); std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), ReverseCompareNodeTimeConnected);
vEvictionCandidates.erase(vEvictionCandidates.end() - static_cast<int>(vEvictionCandidates.size() / 2), vEvictionCandidates.end()); vEvictionCandidates.erase(vEvictionCandidates.end() - static_cast<int>(vEvictionCandidates.size() / 2), vEvictionCandidates.end());
@ -941,6 +949,7 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
vEvictionCandidates = mapAddrCounts[naMostConnections]; vEvictionCandidates = mapAddrCounts[naMostConnections];
// Do not disconnect peers if there is only one unprotected connection from their network group. // Do not disconnect peers if there is only one unprotected connection from their network group.
// This step excessively favors netgroup diversity, and should be removed once more protective criteria are established.
if (vEvictionCandidates.size() <= 1) if (vEvictionCandidates.size() <= 1)
// unless we prefer the new connection (for whitelisted peers) // unless we prefer the new connection (for whitelisted peers)
if (!fPreferNewConnection) if (!fPreferNewConnection)