Changeset View
Changeset View
Standalone View
Standalone View
src/net.cpp
Show First 20 Lines • Show All 922 Lines • ▼ Show 20 Lines | static bool CompareNodeBlockRelayOnlyTime(const NodeEvictionCandidate &a, | ||||
if (a.fRelevantServices != b.fRelevantServices) { | if (a.fRelevantServices != b.fRelevantServices) { | ||||
return b.fRelevantServices; | return b.fRelevantServices; | ||||
} | } | ||||
return a.nTimeConnected > b.nTimeConnected; | return a.nTimeConnected > b.nTimeConnected; | ||||
} | } | ||||
static bool CompareNodeAvailabilityScore(const NodeEvictionCandidate &a, | |||||
const NodeEvictionCandidate &b) { | |||||
// Equality can happen if the nodes have no score or it has not been | |||||
// computed yet. | |||||
if (a.availabilityScore != b.availabilityScore) { | |||||
return a.availabilityScore < b.availabilityScore; | |||||
} | |||||
return a.nTimeConnected > b.nTimeConnected; | |||||
} | |||||
//! Sort an array by the specified comparator, then erase the last K elements. | //! Sort an array by the specified comparator, then erase the last K elements. | ||||
template <typename T, typename Comparator> | template <typename T, typename Comparator> | ||||
static void EraseLastKElements(std::vector<T> &elements, Comparator comparator, | static void EraseLastKElements(std::vector<T> &elements, Comparator comparator, | ||||
size_t k) { | size_t k) { | ||||
std::sort(elements.begin(), elements.end(), comparator); | std::sort(elements.begin(), elements.end(), comparator); | ||||
size_t eraseSize = std::min(k, elements.size()); | size_t eraseSize = std::min(k, elements.size()); | ||||
elements.erase(elements.end() - eraseSize, elements.end()); | elements.erase(elements.end() - eraseSize, elements.end()); | ||||
} | } | ||||
Show All 37 Lines | EraseLastKElementsIf(vEvictionCandidates, CompareNodeBlockRelayOnlyTime, 8, | ||||
[](NodeEvictionCandidate const &n) { | [](NodeEvictionCandidate const &n) { | ||||
return !n.fRelayTxes && n.fRelevantServices; | return !n.fRelayTxes && n.fRelevantServices; | ||||
}); | }); | ||||
// Protect 4 nodes that most recently sent us novel blocks. | // Protect 4 nodes that most recently sent us novel blocks. | ||||
// An attacker cannot manipulate this metric without performing useful work. | // An attacker cannot manipulate this metric without performing useful work. | ||||
EraseLastKElements(vEvictionCandidates, CompareNodeBlockTime, 4); | EraseLastKElements(vEvictionCandidates, CompareNodeBlockTime, 4); | ||||
// Protect up to 128 nodes that have the highest avalanche availability | |||||
// score. | |||||
EraseLastKElementsIf(vEvictionCandidates, CompareNodeAvailabilityScore, 128, | |||||
[](NodeEvictionCandidate const &n) { | |||||
return n.availabilityScore > 0.; | |||||
}); | |||||
// Protect the half of the remaining nodes which have been connected the | // Protect the half of the remaining nodes which have been connected the | ||||
// longest. This replicates the non-eviction implicit behavior, and | // longest. This replicates the non-eviction implicit behavior, and | ||||
// precludes attacks that start later. | // precludes attacks that start later. | ||||
// Reserve half of these protected spots for localhost peers, even if | // Reserve half of these protected spots for localhost peers, even if | ||||
// they're not longest-uptime overall. This helps protect tor peers, which | // they're not longest-uptime overall. This helps protect tor peers, which | ||||
// tend to be otherwise disadvantaged under our eviction criteria. | // tend to be otherwise disadvantaged under our eviction criteria. | ||||
size_t initial_size = vEvictionCandidates.size(); | size_t initial_size = vEvictionCandidates.size(); | ||||
size_t total_protect_size = initial_size / 2; | size_t total_protect_size = initial_size / 2; | ||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | std::vector<NodeEvictionCandidate> vEvictionCandidates; | ||||
} | } | ||||
bool peer_relay_txes = false; | bool peer_relay_txes = false; | ||||
bool peer_filter_not_null = false; | bool peer_filter_not_null = false; | ||||
if (node->m_tx_relay != nullptr) { | if (node->m_tx_relay != nullptr) { | ||||
LOCK(node->m_tx_relay->cs_filter); | LOCK(node->m_tx_relay->cs_filter); | ||||
peer_relay_txes = node->m_tx_relay->fRelayTxes; | peer_relay_txes = node->m_tx_relay->fRelayTxes; | ||||
peer_filter_not_null = node->m_tx_relay->pfilter != nullptr; | peer_filter_not_null = node->m_tx_relay->pfilter != nullptr; | ||||
} | } | ||||
NodeEvictionCandidate candidate = { | NodeEvictionCandidate candidate = { | ||||
node->GetId(), | node->GetId(), | ||||
node->nTimeConnected, | node->nTimeConnected, | ||||
node->nMinPingUsecTime, | node->nMinPingUsecTime, | ||||
node->nLastBlockTime, | node->nLastBlockTime, | ||||
node->nLastProofTime, | node->nLastProofTime, | ||||
node->nLastTXTime, | node->nLastTXTime, | ||||
HasAllDesirableServiceFlags(node->nServices), | HasAllDesirableServiceFlags(node->nServices), | ||||
peer_relay_txes, | peer_relay_txes, | ||||
peer_filter_not_null, | peer_filter_not_null, | ||||
node->nKeyedNetGroup, | node->nKeyedNetGroup, | ||||
node->m_prefer_evict, | node->m_prefer_evict, | ||||
node->addr.IsLocal()}; | node->addr.IsLocal(), | ||||
node->m_avalanche_state | |||||
? node->m_avalanche_state->getAvailabilityScore() | |||||
: -std::numeric_limits<double>::infinity()}; | |||||
vEvictionCandidates.push_back(candidate); | vEvictionCandidates.push_back(candidate); | ||||
} | } | ||||
} | } | ||||
const std::optional<NodeId> node_id_to_evict = | const std::optional<NodeId> node_id_to_evict = | ||||
SelectNodeToEvict(std::move(vEvictionCandidates)); | SelectNodeToEvict(std::move(vEvictionCandidates)); | ||||
if (!node_id_to_evict) { | if (!node_id_to_evict) { | ||||
return false; | return false; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 2,164 Lines • Show Last 20 Lines |