@@ -879,6 +879,26 @@ static void EraseLastKElements(std::vector<T> &elements, Comparator comparator,
879
879
elements.erase (elements.end () - eraseSize, elements.end ());
880
880
}
881
881
882
+ void ProtectEvictionCandidatesByRatio (std::vector<NodeEvictionCandidate>& vEvictionCandidates)
883
+ {
884
+ // Protect the half of the remaining nodes which have been connected the longest.
885
+ // This replicates the non-eviction implicit behavior, and precludes attacks that start later.
886
+ // Reserve half of these protected spots for localhost peers, even if
887
+ // they're not longest-uptime overall. This helps protect tor peers, which
888
+ // tend to be otherwise disadvantaged under our eviction criteria.
889
+ size_t initial_size = vEvictionCandidates.size ();
890
+ size_t total_protect_size = initial_size / 2 ;
891
+
892
+ // Pick out up to 1/4 peers that are localhost, sorted by longest uptime.
893
+ std::sort (vEvictionCandidates.begin (), vEvictionCandidates.end (), CompareLocalHostTimeConnected);
894
+ size_t local_erase_size = total_protect_size / 2 ;
895
+ vEvictionCandidates.erase (std::remove_if (vEvictionCandidates.end () - local_erase_size, vEvictionCandidates.end (), [](NodeEvictionCandidate const &n) { return n.m_is_local ; }), vEvictionCandidates.end ());
896
+ // Calculate how many we removed, and update our total number of peers that
897
+ // we want to protect based on uptime accordingly.
898
+ total_protect_size -= initial_size - vEvictionCandidates.size ();
899
+ EraseLastKElements (vEvictionCandidates, ReverseCompareNodeTimeConnected, total_protect_size);
900
+ }
901
+
882
902
[[nodiscard]] std::optional<NodeId> SelectNodeToEvict (std::vector<NodeEvictionCandidate>&& vEvictionCandidates)
883
903
{
884
904
// Protect connections with certain characteristics
@@ -901,22 +921,9 @@ static void EraseLastKElements(std::vector<T> &elements, Comparator comparator,
901
921
// An attacker cannot manipulate this metric without performing useful work.
902
922
EraseLastKElements (vEvictionCandidates, CompareNodeBlockTime, 4 );
903
923
904
- // Protect the half of the remaining nodes which have been connected the longest.
905
- // This replicates the non-eviction implicit behavior, and precludes attacks that start later.
906
- // Reserve half of these protected spots for localhost peers, even if
907
- // they're not longest-uptime overall. This helps protect tor peers, which
908
- // tend to be otherwise disadvantaged under our eviction criteria.
909
- size_t initial_size = vEvictionCandidates.size ();
910
- size_t total_protect_size = initial_size / 2 ;
911
-
912
- // Pick out up to 1/4 peers that are localhost, sorted by longest uptime.
913
- std::sort (vEvictionCandidates.begin (), vEvictionCandidates.end (), CompareLocalHostTimeConnected);
914
- size_t local_erase_size = total_protect_size / 2 ;
915
- vEvictionCandidates.erase (std::remove_if (vEvictionCandidates.end () - local_erase_size, vEvictionCandidates.end (), [](NodeEvictionCandidate const &n) { return n.m_is_local ; }), vEvictionCandidates.end ());
916
- // Calculate how many we removed, and update our total number of peers that
917
- // we want to protect based on uptime accordingly.
918
- total_protect_size -= initial_size - vEvictionCandidates.size ();
919
- EraseLastKElements (vEvictionCandidates, ReverseCompareNodeTimeConnected, total_protect_size);
924
+ // Protect some of the remaining eviction candidates by ratios of desirable
925
+ // or disadvantaged characteristics.
926
+ ProtectEvictionCandidatesByRatio (vEvictionCandidates);
920
927
921
928
if (vEvictionCandidates.empty ()) return std::nullopt;
922
929
0 commit comments