mirror of
https://github.com/dashpay/dash.git
synced 2024-12-27 04:52:59 +01:00
[net] De-duplicate connection eviction logic
This commit is contained in:
parent
5a9da37fb3
commit
5ce7cb9518
49
src/net.cpp
49
src/net.cpp
@ -962,6 +962,16 @@ static bool CompareNodeTXTime(const NodeEvictionCandidate &a, const NodeEviction
|
||||
return a.nTimeConnected > b.nTimeConnected;
|
||||
}
|
||||
|
||||
|
||||
//! Sort an array by the specified comparator, then erase the last K elements.
|
||||
template<typename T, typename Comparator>
|
||||
static void EraseLastKElements(std::vector<T> &elements, Comparator comparator, size_t k)
|
||||
{
|
||||
std::sort(elements.begin(), elements.end(), comparator);
|
||||
size_t eraseSize = std::min(k, elements.size());
|
||||
elements.erase(elements.end() - eraseSize, elements.end());
|
||||
}
|
||||
|
||||
/** 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.
|
||||
@ -991,42 +1001,23 @@ bool CConnman::AttemptToEvictConnection()
|
||||
}
|
||||
}
|
||||
|
||||
if (vEvictionCandidates.empty()) return false;
|
||||
|
||||
// Protect connections with certain characteristics
|
||||
|
||||
// Deterministically select 4 peers to protect by netgroup.
|
||||
// An attacker cannot predict which netgroups will be protected
|
||||
std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), CompareNetGroupKeyed);
|
||||
vEvictionCandidates.erase(vEvictionCandidates.end() - std::min(4, static_cast<int>(vEvictionCandidates.size())), vEvictionCandidates.end());
|
||||
|
||||
if (vEvictionCandidates.empty()) return false;
|
||||
|
||||
EraseLastKElements(vEvictionCandidates, CompareNetGroupKeyed, 4);
|
||||
// Protect the 8 nodes with the lowest minimum ping time.
|
||||
// An attacker cannot manipulate this metric without physically moving nodes closer to the target.
|
||||
std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), ReverseCompareNodeMinPingTime);
|
||||
vEvictionCandidates.erase(vEvictionCandidates.end() - std::min(8, static_cast<int>(vEvictionCandidates.size())), vEvictionCandidates.end());
|
||||
|
||||
if (vEvictionCandidates.empty()) return false;
|
||||
|
||||
EraseLastKElements(vEvictionCandidates, ReverseCompareNodeMinPingTime, 8);
|
||||
// Protect 4 nodes that most recently sent us transactions.
|
||||
// An attacker cannot manipulate this metric without performing useful work.
|
||||
std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), CompareNodeTXTime);
|
||||
vEvictionCandidates.erase(vEvictionCandidates.end() - std::min(4, static_cast<int>(vEvictionCandidates.size())), vEvictionCandidates.end());
|
||||
|
||||
if (vEvictionCandidates.empty()) return false;
|
||||
|
||||
EraseLastKElements(vEvictionCandidates, CompareNodeTXTime, 4);
|
||||
// Protect 4 nodes that most recently sent us blocks.
|
||||
// An attacker cannot manipulate this metric without performing useful work.
|
||||
std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), CompareNodeBlockTime);
|
||||
vEvictionCandidates.erase(vEvictionCandidates.end() - std::min(4, static_cast<int>(vEvictionCandidates.size())), vEvictionCandidates.end());
|
||||
|
||||
if (vEvictionCandidates.empty()) return false;
|
||||
|
||||
EraseLastKElements(vEvictionCandidates, CompareNodeBlockTime, 4);
|
||||
// Protect the half of the remaining nodes which have been connected the longest.
|
||||
// This replicates the non-eviction implicit behavior, and precludes attacks that start later.
|
||||
std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), ReverseCompareNodeTimeConnected);
|
||||
vEvictionCandidates.erase(vEvictionCandidates.end() - static_cast<int>(vEvictionCandidates.size() / 2), vEvictionCandidates.end());
|
||||
EraseLastKElements(vEvictionCandidates, ReverseCompareNodeTimeConnected, vEvictionCandidates.size() / 2);
|
||||
|
||||
if (vEvictionCandidates.empty()) return false;
|
||||
|
||||
@ -1037,12 +1028,12 @@ bool CConnman::AttemptToEvictConnection()
|
||||
int64_t nMostConnectionsTime = 0;
|
||||
std::map<uint64_t, std::vector<NodeEvictionCandidate> > mapNetGroupNodes;
|
||||
for (const NodeEvictionCandidate &node : vEvictionCandidates) {
|
||||
mapNetGroupNodes[node.nKeyedNetGroup].push_back(node);
|
||||
int64_t grouptime = mapNetGroupNodes[node.nKeyedNetGroup][0].nTimeConnected;
|
||||
size_t groupsize = mapNetGroupNodes[node.nKeyedNetGroup].size();
|
||||
std::vector<NodeEvictionCandidate> &group = mapNetGroupNodes[node.nKeyedNetGroup];
|
||||
group.push_back(node);
|
||||
int64_t grouptime = group[0].nTimeConnected;
|
||||
|
||||
if (groupsize > nMostConnections || (groupsize == nMostConnections && grouptime > nMostConnectionsTime)) {
|
||||
nMostConnections = groupsize;
|
||||
if (group.size() > nMostConnections || (group.size() == nMostConnections && grouptime > nMostConnectionsTime)) {
|
||||
nMostConnections = group.size();
|
||||
nMostConnectionsTime = grouptime;
|
||||
naMostConnections = node.nKeyedNetGroup;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user