Bitcoin Core 22.99.0
P2P Digital Currency
net_peer_eviction_tests.cpp
Go to the documentation of this file.
1// Copyright (c) 2021 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <netaddress.h>
6#include <net.h>
7#include <test/util/net.h>
9
10#include <boost/test/unit_test.hpp>
11
12#include <algorithm>
13#include <functional>
14#include <optional>
15#include <unordered_set>
16#include <vector>
17
18BOOST_FIXTURE_TEST_SUITE(net_peer_eviction_tests, BasicTestingSetup)
19
20// Create `num_peers` random nodes, apply setup function `candidate_setup_fn`,
21// call ProtectEvictionCandidatesByRatio() to apply protection logic, and then
22// return true if all of `protected_peer_ids` and none of `unprotected_peer_ids`
23// are protected from eviction, i.e. removed from the eviction candidates.
24bool IsProtected(int num_peers,
25 std::function<void(NodeEvictionCandidate&)> candidate_setup_fn,
26 const std::unordered_set<NodeId>& protected_peer_ids,
27 const std::unordered_set<NodeId>& unprotected_peer_ids,
28 FastRandomContext& random_context)
29{
30 std::vector<NodeEvictionCandidate> candidates{GetRandomNodeEvictionCandidates(num_peers, random_context)};
31 for (NodeEvictionCandidate& candidate : candidates) {
32 candidate_setup_fn(candidate);
33 }
34 Shuffle(candidates.begin(), candidates.end(), random_context);
35
36 const size_t size{candidates.size()};
37 const size_t expected{size - size / 2}; // Expect half the candidates will be protected.
39 BOOST_CHECK_EQUAL(candidates.size(), expected);
40
41 size_t unprotected_count{0};
42 for (const NodeEvictionCandidate& candidate : candidates) {
43 if (protected_peer_ids.count(candidate.id)) {
44 // this peer should have been removed from the eviction candidates
45 BOOST_TEST_MESSAGE(strprintf("expected candidate to be protected: %d", candidate.id));
46 return false;
47 }
48 if (unprotected_peer_ids.count(candidate.id)) {
49 // this peer remains in the eviction candidates, as expected
50 ++unprotected_count;
51 }
52 }
53
54 const bool is_protected{unprotected_count == unprotected_peer_ids.size()};
55 if (!is_protected) {
56 BOOST_TEST_MESSAGE(strprintf("unprotected: expected %d, actual %d",
57 unprotected_peer_ids.size(), unprotected_count));
58 }
59 return is_protected;
60}
61
62BOOST_AUTO_TEST_CASE(peer_protection_test)
63{
64 FastRandomContext random_context{true};
65 int num_peers{12};
66
67 // Expect half of the peers with greatest uptime (the lowest nTimeConnected)
68 // to be protected from eviction.
70 num_peers, [](NodeEvictionCandidate& c) {
71 c.nTimeConnected = c.id;
72 c.m_is_local = false;
74 },
75 /* protected_peer_ids */ {0, 1, 2, 3, 4, 5},
76 /* unprotected_peer_ids */ {6, 7, 8, 9, 10, 11},
77 random_context));
78
79 // Verify in the opposite direction.
81 num_peers, [num_peers](NodeEvictionCandidate& c) {
82 c.nTimeConnected = num_peers - c.id;
83 c.m_is_local = false;
85 },
86 /* protected_peer_ids */ {6, 7, 8, 9, 10, 11},
87 /* unprotected_peer_ids */ {0, 1, 2, 3, 4, 5},
88 random_context));
89
90 // Test protection of onion, localhost, and I2P peers...
91
92 // Expect 1/4 onion peers to be protected from eviction,
93 // if no localhost or I2P peers.
95 num_peers, [](NodeEvictionCandidate& c) {
96 c.m_is_local = false;
97 c.m_network = (c.id == 3 || c.id == 8 || c.id == 9) ? NET_ONION : NET_IPV4;
98 },
99 /* protected_peer_ids */ {3, 8, 9},
100 /* unprotected_peer_ids */ {},
101 random_context));
102
103 // Expect 1/4 onion peers and 1/4 of the other peers to be protected,
104 // sorted by longest uptime (lowest nTimeConnected), if no localhost or I2P peers.
106 num_peers, [](NodeEvictionCandidate& c) {
107 c.nTimeConnected = c.id;
108 c.m_is_local = false;
109 c.m_network = (c.id == 3 || c.id > 7) ? NET_ONION : NET_IPV6;
110 },
111 /* protected_peer_ids */ {0, 1, 2, 3, 8, 9},
112 /* unprotected_peer_ids */ {4, 5, 6, 7, 10, 11},
113 random_context));
114
115 // Expect 1/4 localhost peers to be protected from eviction,
116 // if no onion or I2P peers.
118 num_peers, [](NodeEvictionCandidate& c) {
119 c.m_is_local = (c.id == 1 || c.id == 9 || c.id == 11);
121 },
122 /* protected_peer_ids */ {1, 9, 11},
123 /* unprotected_peer_ids */ {},
124 random_context));
125
126 // Expect 1/4 localhost peers and 1/4 of the other peers to be protected,
127 // sorted by longest uptime (lowest nTimeConnected), if no onion or I2P peers.
129 num_peers, [](NodeEvictionCandidate& c) {
130 c.nTimeConnected = c.id;
131 c.m_is_local = (c.id > 6);
133 },
134 /* protected_peer_ids */ {0, 1, 2, 7, 8, 9},
135 /* unprotected_peer_ids */ {3, 4, 5, 6, 10, 11},
136 random_context));
137
138 // Expect 1/4 I2P peers to be protected from eviction,
139 // if no onion or localhost peers.
141 num_peers, [](NodeEvictionCandidate& c) {
142 c.m_is_local = false;
143 c.m_network = (c.id == 2 || c.id == 7 || c.id == 10) ? NET_I2P : NET_IPV4;
144 },
145 /* protected_peer_ids */ {2, 7, 10},
146 /* unprotected_peer_ids */ {},
147 random_context));
148
149 // Expect 1/4 I2P peers and 1/4 of the other peers to be protected,
150 // sorted by longest uptime (lowest nTimeConnected), if no onion or localhost peers.
152 num_peers, [](NodeEvictionCandidate& c) {
153 c.nTimeConnected = c.id;
154 c.m_is_local = false;
155 c.m_network = (c.id == 4 || c.id > 8) ? NET_I2P : NET_IPV6;
156 },
157 /* protected_peer_ids */ {0, 1, 2, 4, 9, 10},
158 /* unprotected_peer_ids */ {3, 5, 6, 7, 8, 11},
159 random_context));
160
161 // Tests with 2 networks...
162
163 // Combined test: expect having 1 localhost and 1 onion peer out of 4 to
164 // protect 1 localhost, 0 onion and 1 other peer, sorted by longest uptime;
165 // stable sort breaks tie with array order of localhost first.
167 4, [](NodeEvictionCandidate& c) {
168 c.nTimeConnected = c.id;
169 c.m_is_local = (c.id == 4);
170 c.m_network = (c.id == 3) ? NET_ONION : NET_IPV4;
171 },
172 /* protected_peer_ids */ {0, 4},
173 /* unprotected_peer_ids */ {1, 2},
174 random_context));
175
176 // Combined test: expect having 1 localhost and 1 onion peer out of 7 to
177 // protect 1 localhost, 0 onion, and 2 other peers (3 total), sorted by
178 // uptime; stable sort breaks tie with array order of localhost first.
180 7, [](NodeEvictionCandidate& c) {
181 c.nTimeConnected = c.id;
182 c.m_is_local = (c.id == 6);
183 c.m_network = (c.id == 5) ? NET_ONION : NET_IPV4;
184 },
185 /* protected_peer_ids */ {0, 1, 6},
186 /* unprotected_peer_ids */ {2, 3, 4, 5},
187 random_context));
188
189 // Combined test: expect having 1 localhost and 1 onion peer out of 8 to
190 // protect protect 1 localhost, 1 onion and 2 other peers (4 total), sorted
191 // by uptime; stable sort breaks tie with array order of localhost first.
193 8, [](NodeEvictionCandidate& c) {
194 c.nTimeConnected = c.id;
195 c.m_is_local = (c.id == 6);
196 c.m_network = (c.id == 5) ? NET_ONION : NET_IPV4;
197 },
198 /* protected_peer_ids */ {0, 1, 5, 6},
199 /* unprotected_peer_ids */ {2, 3, 4, 7},
200 random_context));
201
202 // Combined test: expect having 3 localhost and 3 onion peers out of 12 to
203 // protect 2 localhost and 1 onion, plus 3 other peers, sorted by longest
204 // uptime; stable sort breaks ties with the array order of localhost first.
206 num_peers, [](NodeEvictionCandidate& c) {
207 c.nTimeConnected = c.id;
208 c.m_is_local = (c.id == 6 || c.id == 9 || c.id == 11);
209 c.m_network = (c.id == 7 || c.id == 8 || c.id == 10) ? NET_ONION : NET_IPV6;
210 },
211 /* protected_peer_ids */ {0, 1, 2, 6, 7, 9},
212 /* unprotected_peer_ids */ {3, 4, 5, 8, 10, 11},
213 random_context));
214
215 // Combined test: expect having 4 localhost and 1 onion peer out of 12 to
216 // protect 2 localhost and 1 onion, plus 3 other peers, sorted by longest uptime.
218 num_peers, [](NodeEvictionCandidate& c) {
219 c.nTimeConnected = c.id;
220 c.m_is_local = (c.id > 4 && c.id < 9);
221 c.m_network = (c.id == 10) ? NET_ONION : NET_IPV4;
222 },
223 /* protected_peer_ids */ {0, 1, 2, 5, 6, 10},
224 /* unprotected_peer_ids */ {3, 4, 7, 8, 9, 11},
225 random_context));
226
227 // Combined test: expect having 4 localhost and 2 onion peers out of 16 to
228 // protect 2 localhost and 2 onions, plus 4 other peers, sorted by longest uptime.
230 16, [](NodeEvictionCandidate& c) {
231 c.nTimeConnected = c.id;
232 c.m_is_local = (c.id == 6 || c.id == 9 || c.id == 11 || c.id == 12);
233 c.m_network = (c.id == 8 || c.id == 10) ? NET_ONION : NET_IPV6;
234 },
235 /* protected_peer_ids */ {0, 1, 2, 3, 6, 8, 9, 10},
236 /* unprotected_peer_ids */ {4, 5, 7, 11, 12, 13, 14, 15},
237 random_context));
238
239 // Combined test: expect having 5 localhost and 1 onion peer out of 16 to
240 // protect 3 localhost (recovering the unused onion slot), 1 onion, and 4
241 // others, sorted by longest uptime.
243 16, [](NodeEvictionCandidate& c) {
244 c.nTimeConnected = c.id;
245 c.m_is_local = (c.id > 10);
246 c.m_network = (c.id == 10) ? NET_ONION : NET_IPV4;
247 },
248 /* protected_peer_ids */ {0, 1, 2, 3, 10, 11, 12, 13},
249 /* unprotected_peer_ids */ {4, 5, 6, 7, 8, 9, 14, 15},
250 random_context));
251
252 // Combined test: expect having 1 localhost and 4 onion peers out of 16 to
253 // protect 1 localhost and 3 onions (recovering the unused localhost slot),
254 // plus 4 others, sorted by longest uptime.
256 16, [](NodeEvictionCandidate& c) {
257 c.nTimeConnected = c.id;
258 c.m_is_local = (c.id == 15);
259 c.m_network = (c.id > 6 && c.id < 11) ? NET_ONION : NET_IPV6;
260 },
261 /* protected_peer_ids */ {0, 1, 2, 3, 7, 8, 9, 15},
262 /* unprotected_peer_ids */ {5, 6, 10, 11, 12, 13, 14},
263 random_context));
264
265 // Combined test: expect having 2 onion and 4 I2P out of 12 peers to protect
266 // 2 onion (prioritized for having fewer candidates) and 1 I2P, plus 3
267 // others, sorted by longest uptime.
269 num_peers, [](NodeEvictionCandidate& c) {
270 c.nTimeConnected = c.id;
271 c.m_is_local = false;
272 if (c.id == 8 || c.id == 10) {
273 c.m_network = NET_ONION;
274 } else if (c.id == 6 || c.id == 9 || c.id == 11 || c.id == 12) {
275 c.m_network = NET_I2P;
276 } else {
277 c.m_network = NET_IPV4;
278 }
279 },
280 /* protected_peer_ids */ {0, 1, 2, 6, 8, 10},
281 /* unprotected_peer_ids */ {3, 4, 5, 7, 9, 11},
282 random_context));
283
284 // Tests with 3 networks...
285
286 // Combined test: expect having 1 localhost, 1 I2P and 1 onion peer out of 4
287 // to protect 1 I2P, 0 localhost, 0 onion and 1 other peer (2 total), sorted
288 // by longest uptime; stable sort breaks tie with array order of I2P first.
290 4, [](NodeEvictionCandidate& c) {
291 c.nTimeConnected = c.id;
292 c.m_is_local = (c.id == 3);
293 if (c.id == 4) {
294 c.m_network = NET_I2P;
295 } else if (c.id == 2) {
296 c.m_network = NET_ONION;
297 } else {
298 c.m_network = NET_IPV6;
299 }
300 },
301 /* protected_peer_ids */ {0, 4},
302 /* unprotected_peer_ids */ {1, 2},
303 random_context));
304
305 // Combined test: expect having 1 localhost, 1 I2P and 1 onion peer out of 7
306 // to protect 1 I2P, 0 localhost, 0 onion and 2 other peers (3 total) sorted
307 // by longest uptime; stable sort breaks tie with array order of I2P first.
309 7, [](NodeEvictionCandidate& c) {
310 c.nTimeConnected = c.id;
311 c.m_is_local = (c.id == 4);
312 if (c.id == 6) {
313 c.m_network = NET_I2P;
314 } else if (c.id == 5) {
315 c.m_network = NET_ONION;
316 } else {
317 c.m_network = NET_IPV6;
318 }
319 },
320 /* protected_peer_ids */ {0, 1, 6},
321 /* unprotected_peer_ids */ {2, 3, 4, 5},
322 random_context));
323
324 // Combined test: expect having 1 localhost, 1 I2P and 1 onion peer out of 8
325 // to protect 1 I2P, 1 localhost, 0 onion and 2 other peers (4 total) sorted
326 // by uptime; stable sort breaks tie with array order of I2P then localhost.
328 8, [](NodeEvictionCandidate& c) {
329 c.nTimeConnected = c.id;
330 c.m_is_local = (c.id == 6);
331 if (c.id == 5) {
332 c.m_network = NET_I2P;
333 } else if (c.id == 4) {
334 c.m_network = NET_ONION;
335 } else {
336 c.m_network = NET_IPV6;
337 }
338 },
339 /* protected_peer_ids */ {0, 1, 5, 6},
340 /* unprotected_peer_ids */ {2, 3, 4, 7},
341 random_context));
342
343 // Combined test: expect having 4 localhost, 2 I2P, and 2 onion peers out of
344 // 16 to protect 1 localhost, 2 I2P, and 1 onion (4/16 total), plus 4 others
345 // for 8 total, sorted by longest uptime.
347 16, [](NodeEvictionCandidate& c) {
348 c.nTimeConnected = c.id;
349 c.m_is_local = (c.id == 6 || c.id > 11);
350 if (c.id == 7 || c.id == 11) {
351 c.m_network = NET_I2P;
352 } else if (c.id == 9 || c.id == 10) {
353 c.m_network = NET_ONION;
354 } else {
355 c.m_network = NET_IPV4;
356 }
357 },
358 /* protected_peer_ids */ {0, 1, 2, 3, 6, 7, 9, 11},
359 /* unprotected_peer_ids */ {4, 5, 8, 10, 12, 13, 14, 15},
360 random_context));
361
362 // Combined test: expect having 1 localhost, 8 I2P and 1 onion peer out of
363 // 24 to protect 1, 4, and 1 (6 total), plus 6 others for 12/24 total,
364 // sorted by longest uptime.
366 24, [](NodeEvictionCandidate& c) {
367 c.nTimeConnected = c.id;
368 c.m_is_local = (c.id == 12);
369 if (c.id > 14 && c.id < 23) { // 4 protected instead of usual 2
370 c.m_network = NET_I2P;
371 } else if (c.id == 23) {
372 c.m_network = NET_ONION;
373 } else {
374 c.m_network = NET_IPV6;
375 }
376 },
377 /* protected_peer_ids */ {0, 1, 2, 3, 4, 5, 12, 15, 16, 17, 18, 23},
378 /* unprotected_peer_ids */ {6, 7, 8, 9, 10, 11, 13, 14, 19, 20, 21, 22},
379 random_context));
380
381 // Combined test: expect having 1 localhost, 3 I2P and 6 onion peers out of
382 // 24 to protect 1, 3, and 2 (6 total, I2P has fewer candidates and so gets the
383 // unused localhost slot), plus 6 others for 12/24 total, sorted by longest uptime.
385 24, [](NodeEvictionCandidate& c) {
386 c.nTimeConnected = c.id;
387 c.m_is_local = (c.id == 15);
388 if (c.id == 12 || c.id == 14 || c.id == 17) {
389 c.m_network = NET_I2P;
390 } else if (c.id > 17) { // 4 protected instead of usual 2
391 c.m_network = NET_ONION;
392 } else {
393 c.m_network = NET_IPV4;
394 }
395 },
396 /* protected_peer_ids */ {0, 1, 2, 3, 4, 5, 12, 14, 15, 17, 18, 19},
397 /* unprotected_peer_ids */ {6, 7, 8, 9, 10, 11, 13, 16, 20, 21, 22, 23},
398 random_context));
399
400 // Combined test: expect having 1 localhost, 7 I2P and 4 onion peers out of
401 // 24 to protect 1 localhost, 2 I2P, and 3 onions (6 total), plus 6 others
402 // for 12/24 total, sorted by longest uptime.
404 24, [](NodeEvictionCandidate& c) {
405 c.nTimeConnected = c.id;
406 c.m_is_local = (c.id == 13);
407 if (c.id > 16) {
408 c.m_network = NET_I2P;
409 } else if (c.id == 12 || c.id == 14 || c.id == 15 || c.id == 16) {
410 c.m_network = NET_ONION;
411 } else {
412 c.m_network = NET_IPV6;
413 }
414 },
415 /* protected_peer_ids */ {0, 1, 2, 3, 4, 5, 12, 13, 14, 15, 17, 18},
416 /* unprotected_peer_ids */ {6, 7, 8, 9, 10, 11, 16, 19, 20, 21, 22, 23},
417 random_context));
418
419 // Combined test: expect having 8 localhost, 4 I2P, and 3 onion peers out of
420 // 24 to protect 2 of each (6 total), plus 6 others for 12/24 total, sorted
421 // by longest uptime.
423 24, [](NodeEvictionCandidate& c) {
424 c.nTimeConnected = c.id;
425 c.m_is_local = (c.id > 15);
426 if (c.id > 10 && c.id < 15) {
427 c.m_network = NET_I2P;
428 } else if (c.id > 6 && c.id < 10) {
429 c.m_network = NET_ONION;
430 } else {
431 c.m_network = NET_IPV4;
432 }
433 },
434 /* protected_peer_ids */ {0, 1, 2, 3, 4, 5, 7, 8, 11, 12, 16, 17},
435 /* unprotected_peer_ids */ {6, 9, 10, 13, 14, 15, 18, 19, 20, 21, 22, 23},
436 random_context));
437}
438
439// Returns true if any of the node ids in node_ids are selected for eviction.
440bool IsEvicted(std::vector<NodeEvictionCandidate> candidates, const std::unordered_set<NodeId>& node_ids, FastRandomContext& random_context)
441{
442 Shuffle(candidates.begin(), candidates.end(), random_context);
443 const std::optional<NodeId> evicted_node_id = SelectNodeToEvict(std::move(candidates));
444 if (!evicted_node_id) {
445 return false;
446 }
447 return node_ids.count(*evicted_node_id);
448}
449
450// Create number_of_nodes random nodes, apply setup function candidate_setup_fn,
451// apply eviction logic and then return true if any of the node ids in node_ids
452// are selected for eviction.
453bool IsEvicted(const int number_of_nodes, std::function<void(NodeEvictionCandidate&)> candidate_setup_fn, const std::unordered_set<NodeId>& node_ids, FastRandomContext& random_context)
454{
455 std::vector<NodeEvictionCandidate> candidates = GetRandomNodeEvictionCandidates(number_of_nodes, random_context);
456 for (NodeEvictionCandidate& candidate : candidates) {
457 candidate_setup_fn(candidate);
458 }
459 return IsEvicted(candidates, node_ids, random_context);
460}
461
462BOOST_AUTO_TEST_CASE(peer_eviction_test)
463{
464 FastRandomContext random_context{true};
465
466 for (int number_of_nodes = 0; number_of_nodes < 200; ++number_of_nodes) {
467 // Four nodes with the highest keyed netgroup values should be
468 // protected from eviction.
470 number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) {
471 candidate.nKeyedNetGroup = number_of_nodes - candidate.id;
472 },
473 {0, 1, 2, 3}, random_context));
474
475 // Eight nodes with the lowest minimum ping time should be protected
476 // from eviction.
478 number_of_nodes, [](NodeEvictionCandidate& candidate) {
479 candidate.m_min_ping_time = std::chrono::microseconds{candidate.id};
480 },
481 {0, 1, 2, 3, 4, 5, 6, 7}, random_context));
482
483 // Four nodes that most recently sent us novel transactions accepted
484 // into our mempool should be protected from eviction.
486 number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) {
487 candidate.nLastTXTime = number_of_nodes - candidate.id;
488 },
489 {0, 1, 2, 3}, random_context));
490
491 // Up to eight non-tx-relay peers that most recently sent us novel
492 // blocks should be protected from eviction.
494 number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) {
495 candidate.nLastBlockTime = number_of_nodes - candidate.id;
496 if (candidate.id <= 7) {
497 candidate.fRelayTxes = false;
498 candidate.fRelevantServices = true;
499 }
500 },
501 {0, 1, 2, 3, 4, 5, 6, 7}, random_context));
502
503 // Four peers that most recently sent us novel blocks should be
504 // protected from eviction.
506 number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) {
507 candidate.nLastBlockTime = number_of_nodes - candidate.id;
508 },
509 {0, 1, 2, 3}, random_context));
510
511 // Combination of the previous two tests.
513 number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) {
514 candidate.nLastBlockTime = number_of_nodes - candidate.id;
515 if (candidate.id <= 7) {
516 candidate.fRelayTxes = false;
517 candidate.fRelevantServices = true;
518 }
519 },
520 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, random_context));
521
522 // Combination of all tests above.
524 number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) {
525 candidate.nKeyedNetGroup = number_of_nodes - candidate.id; // 4 protected
526 candidate.m_min_ping_time = std::chrono::microseconds{candidate.id}; // 8 protected
527 candidate.nLastTXTime = number_of_nodes - candidate.id; // 4 protected
528 candidate.nLastBlockTime = number_of_nodes - candidate.id; // 4 protected
529 },
530 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}, random_context));
531
532 // An eviction is expected given >= 29 random eviction candidates. The eviction logic protects at most
533 // four peers by net group, eight by lowest ping time, four by last time of novel tx, up to eight non-tx-relay
534 // peers by last novel block time, and four more peers by last novel block time.
535 if (number_of_nodes >= 29) {
536 BOOST_CHECK(SelectNodeToEvict(GetRandomNodeEvictionCandidates(number_of_nodes, random_context)));
537 }
538
539 // No eviction is expected given <= 20 random eviction candidates. The eviction logic protects at least
540 // four peers by net group, eight by lowest ping time, four by last time of novel tx and four peers by last
541 // novel block time.
542 if (number_of_nodes <= 20) {
543 BOOST_CHECK(!SelectNodeToEvict(GetRandomNodeEvictionCandidates(number_of_nodes, random_context)));
544 }
545
546 // Cases left to test:
547 // * "If any remaining peers are preferred for eviction consider only them. [...]"
548 // * "Identify the network group with the most connections and youngest member. [...]"
549 }
550}
551
Fast randomness source.
Definition: random.h:120
BOOST_AUTO_TEST_SUITE_END()
if(na.IsAddrV1Compatible())
void ProtectEvictionCandidatesByRatio(std::vector< NodeEvictionCandidate > &eviction_candidates)
Protect desirable or disadvantaged inbound peers from eviction by ratio.
Definition: net.cpp:913
std::optional< NodeId > SelectNodeToEvict(std::vector< NodeEvictionCandidate > &&vEvictionCandidates)
Select an inbound peer to evict after filtering out (protecting) peers having distinct,...
Definition: net.cpp:986
int64_t NodeId
Definition: net.h:87
bool IsEvicted(std::vector< NodeEvictionCandidate > candidates, const std::unordered_set< NodeId > &node_ids, FastRandomContext &random_context)
BOOST_AUTO_TEST_CASE(peer_protection_test)
bool IsProtected(int num_peers, std::function< void(NodeEvictionCandidate &)> candidate_setup_fn, const std::unordered_set< NodeId > &protected_peer_ids, const std::unordered_set< NodeId > &unprotected_peer_ids, FastRandomContext &random_context)
@ NET_I2P
I2P.
Definition: netaddress.h:59
@ NET_ONION
TOR (v2 or v3)
Definition: netaddress.h:56
@ NET_IPV6
IPv6.
Definition: netaddress.h:53
@ NET_IPV4
IPv4.
Definition: netaddress.h:50
#define BOOST_FIXTURE_TEST_SUITE(a, b)
Definition: object.cpp:14
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
#define BOOST_CHECK(expr)
Definition: object.cpp:17
void Shuffle(I first, I last, R &&rng)
More efficient than using std::shuffle on a FastRandomContext.
Definition: random.h:231
Basic testing setup.
Definition: setup_common.h:76
int64_t nLastBlockTime
Definition: net.h:1195
Network m_network
Definition: net.h:1203
int64_t nTimeConnected
Definition: net.h:1193
int64_t nLastTXTime
Definition: net.h:1196
std::chrono::microseconds m_min_ping_time
Definition: net.h:1194
uint64_t nKeyedNetGroup
Definition: net.h:1200
std::vector< NodeEvictionCandidate > GetRandomNodeEvictionCandidates(int n_candidates, FastRandomContext &random_context)
Definition: net.cpp:44
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1164