Branch data Line data Source code
1 : : // Copyright (c) 2012-2022 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 <addrdb.h>
6 : : #include <addrman.h>
7 : : #include <addrman_impl.h>
8 : : #include <chainparams.h>
9 : : #include <clientversion.h>
10 : : #include <hash.h>
11 : : #include <netbase.h>
12 : : #include <random.h>
13 : : #include <test/data/asmap.raw.h>
14 : : #include <test/util/setup_common.h>
15 : : #include <util/asmap.h>
16 : : #include <util/string.h>
17 : :
18 : : #include <boost/test/unit_test.hpp>
19 : :
20 : : #include <optional>
21 : : #include <string>
22 : :
23 : : using namespace std::literals;
24 : : using node::NodeContext;
25 : : using util::ToString;
26 : :
27 : : static NetGroupManager EMPTY_NETGROUPMAN{std::vector<bool>()};
28 : : static const bool DETERMINISTIC{true};
29 : :
30 : 24 : static int32_t GetCheckRatio(const NodeContext& node_ctx)
31 : : {
32 [ + - + - ]: 48 : return std::clamp<int32_t>(node_ctx.args->GetIntArg("-checkaddrman", 100), 0, 1000000);
33 : : }
34 : :
35 : 6819 : static CNetAddr ResolveIP(const std::string& ip)
36 : : {
37 [ + - ]: 6819 : const std::optional<CNetAddr> addr{LookupHost(ip, false)};
38 [ + - + - : 13638 : BOOST_CHECK_MESSAGE(addr.has_value(), strprintf("failed to resolve: %s", ip));
+ - ]
39 [ + - ]: 6819 : return addr.value_or(CNetAddr{});
40 : 6819 : }
41 : :
42 : 6629 : static CService ResolveService(const std::string& ip, uint16_t port = 0)
43 : : {
44 [ + - ]: 6629 : const std::optional<CService> serv{Lookup(ip, port, false)};
45 [ + - + - : 13258 : BOOST_CHECK_MESSAGE(serv.has_value(), strprintf("failed to resolve: %s:%i", ip, port));
+ - ]
46 [ + - ]: 6629 : return serv.value_or(CService{});
47 : 6629 : }
48 : :
49 : :
50 : 3 : static std::vector<bool> FromBytes(const unsigned char* source, int vector_size)
51 : : {
52 : 3 : std::vector<bool> result(vector_size);
53 [ + + ]: 180 : for (int byte_i = 0; byte_i < vector_size / 8; ++byte_i) {
54 : 177 : unsigned char cur_byte = source[byte_i];
55 [ + + ]: 1593 : for (int bit_i = 0; bit_i < 8; ++bit_i) {
56 : 1416 : result[byte_i * 8 + bit_i] = (cur_byte >> bit_i) & 1;
57 : : }
58 : : }
59 : 3 : return result;
60 : : }
61 : :
62 : : BOOST_FIXTURE_TEST_SUITE(addrman_tests, BasicTestingSetup)
63 : :
64 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(addrman_simple)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
65 : : {
66 : 1 : auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
67 : :
68 [ + - + - ]: 1 : CNetAddr source = ResolveIP("252.2.2.2");
69 : :
70 : : // Test: Does Addrman respond correctly when empty.
71 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(), 0U);
+ - ]
72 [ + - ]: 1 : auto addr_null = addrman->Select().first;
73 [ + - + - : 1 : BOOST_CHECK_EQUAL(addr_null.ToStringAddrPort(), "[::]:0");
+ - ]
74 : :
75 : : // Test: Does Addrman::Add work as expected.
76 [ + - + - ]: 1 : CService addr1 = ResolveService("250.1.1.1", 8333);
77 [ + - + - : 5 : BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
78 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(), 1U);
+ - ]
79 [ + - ]: 1 : auto addr_ret1 = addrman->Select().first;
80 [ + - + - : 1 : BOOST_CHECK_EQUAL(addr_ret1.ToStringAddrPort(), "250.1.1.1:8333");
+ - ]
81 : :
82 : : // Test: Does IP address deduplication work correctly.
83 : : // Expected dup IP should not be added.
84 [ + - + - ]: 1 : CService addr1_dup = ResolveService("250.1.1.1", 8333);
85 [ + - + - : 5 : BOOST_CHECK(!addrman->Add({CAddress(addr1_dup, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
86 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(), 1U);
+ - ]
87 : :
88 : :
89 : : // Test: New table has one addr and we add a diff addr we should
90 : : // have at least one addr.
91 : : // Note that addrman's size cannot be tested reliably after insertion, as
92 : : // hash collisions may occur. But we can always be sure of at least one
93 : : // success.
94 : :
95 [ + - + - ]: 1 : CService addr2 = ResolveService("250.1.1.2", 8333);
96 [ + - + - : 5 : BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
97 [ + - + - : 2 : BOOST_CHECK(addrman->Size() >= 1);
+ - + - ]
98 : :
99 : : // Test: reset addrman and test AddrMan::Add multiple addresses works as expected
100 [ + - + - ]: 2 : addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
101 : 1 : std::vector<CAddress> vAddr;
102 [ + - + - : 2 : vAddr.emplace_back(ResolveService("250.1.1.3", 8333), NODE_NONE);
+ - ]
103 [ + - + - : 2 : vAddr.emplace_back(ResolveService("250.1.1.4", 8333), NODE_NONE);
+ - ]
104 [ + - + - : 2 : BOOST_CHECK(addrman->Add(vAddr, source));
+ - + - ]
105 [ + - + - : 2 : BOOST_CHECK(addrman->Size() >= 1);
+ - ]
106 : 4 : }
107 : :
108 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(addrman_ports)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
109 : : {
110 : 1 : auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
111 : :
112 [ + - + - ]: 1 : CNetAddr source = ResolveIP("252.2.2.2");
113 : :
114 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(), 0U);
+ - ]
115 : :
116 : : // Test 7; Addr with same IP but diff port does not replace existing addr.
117 [ + - + - ]: 1 : CService addr1 = ResolveService("250.1.1.1", 8333);
118 [ + - + - : 5 : BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
119 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(), 1U);
+ - ]
120 : :
121 [ + - + - ]: 1 : CService addr1_port = ResolveService("250.1.1.1", 8334);
122 [ + - + - : 5 : BOOST_CHECK(addrman->Add({CAddress(addr1_port, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
123 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(), 2U);
+ - ]
124 [ + - ]: 1 : auto addr_ret2 = addrman->Select().first;
125 [ + - + - : 3 : BOOST_CHECK(addr_ret2.ToStringAddrPort() == "250.1.1.1:8333" || addr_ret2.ToStringAddrPort() == "250.1.1.1:8334");
- + - - -
- + - - +
- - - - ]
126 : :
127 : : // Test: Add same IP but diff port to tried table; this converts the entry with
128 : : // the specified port to tried, but not the other.
129 [ + - ]: 2 : addrman->Good(CAddress(addr1_port, NODE_NONE));
130 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(), 2U);
+ - ]
131 : 1 : bool new_only = true;
132 [ + - ]: 1 : auto addr_ret3 = addrman->Select(new_only).first;
133 [ + - + - : 1 : BOOST_CHECK_EQUAL(addr_ret3.ToStringAddrPort(), "250.1.1.1:8333");
+ - ]
134 : 3 : }
135 : :
136 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(addrman_select)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
137 : : {
138 : 1 : auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
139 [ + - + - : 2 : BOOST_CHECK(!addrman->Select(false).first.IsValid());
+ - + - +
- ]
140 [ + - + - : 2 : BOOST_CHECK(!addrman->Select(true).first.IsValid());
+ - + - +
- ]
141 : :
142 [ + - + - ]: 1 : CNetAddr source = ResolveIP("252.2.2.2");
143 : :
144 : : // Add 1 address to the new table
145 [ + - + - ]: 1 : CService addr1 = ResolveService("250.1.1.1", 8333);
146 [ + - + - : 5 : BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
147 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(), 1U);
+ - ]
148 : :
149 [ + - + - : 2 : BOOST_CHECK(addrman->Select(/*new_only=*/true).first == addr1);
+ - + - +
- ]
150 [ + - + - : 2 : BOOST_CHECK(addrman->Select(/*new_only=*/false).first == addr1);
+ - + - +
- ]
151 : :
152 : : // Move address to the tried table
153 [ + - + - : 2 : BOOST_CHECK(addrman->Good(CAddress(addr1, NODE_NONE)));
+ - + - ]
154 : :
155 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(), 1U);
+ - ]
156 [ + - + - : 2 : BOOST_CHECK(!addrman->Select(/*new_only=*/true).first.IsValid());
+ - + - +
- ]
157 [ + - + - : 2 : BOOST_CHECK(addrman->Select().first == addr1);
+ - + - +
- ]
158 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(), 1U);
+ - ]
159 : :
160 : : // Add one address to the new table
161 [ + - + - : 2 : CService addr2 = ResolveService("250.3.1.1", 8333);
+ - ]
162 [ + - + - : 5 : BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, addr2));
+ - + - +
+ + - -
- ]
163 [ + - + - : 2 : BOOST_CHECK(addrman->Select(/*new_only=*/true).first == addr2);
+ - + - +
- ]
164 : :
165 : : // Add two more addresses to the new table
166 [ + - + - ]: 1 : CService addr3 = ResolveService("250.3.2.2", 9999);
167 [ + - + - ]: 1 : CService addr4 = ResolveService("250.3.3.3", 9999);
168 : :
169 [ + - + - : 5 : BOOST_CHECK(addrman->Add({CAddress(addr3, NODE_NONE)}, addr2));
+ - + - +
+ + - -
- ]
170 [ + - + - : 5 : BOOST_CHECK(addrman->Add({CAddress(addr4, NODE_NONE)}, ResolveService("250.4.1.1", 8333)));
+ - + - +
- + - + +
+ - - - ]
171 : :
172 : : // Add three addresses to tried table.
173 [ + - + - ]: 1 : CService addr5 = ResolveService("250.4.4.4", 8333);
174 [ + - + - ]: 1 : CService addr6 = ResolveService("250.4.5.5", 7777);
175 [ + - + - ]: 1 : CService addr7 = ResolveService("250.4.6.6", 8333);
176 : :
177 [ + - + - : 5 : BOOST_CHECK(addrman->Add({CAddress(addr5, NODE_NONE)}, addr3));
+ - + - +
+ + - -
- ]
178 [ + - + - : 2 : BOOST_CHECK(addrman->Good(CAddress(addr5, NODE_NONE)));
+ - + - ]
179 [ + - + - : 5 : BOOST_CHECK(addrman->Add({CAddress(addr6, NODE_NONE)}, addr3));
+ - + - +
+ + - -
- ]
180 [ + - + - : 2 : BOOST_CHECK(addrman->Good(CAddress(addr6, NODE_NONE)));
+ - + - ]
181 [ + - + - : 5 : BOOST_CHECK(addrman->Add({CAddress(addr7, NODE_NONE)}, ResolveService("250.1.1.3", 8333)));
+ - + - +
- + - + +
+ - - - ]
182 [ + - + - : 2 : BOOST_CHECK(addrman->Good(CAddress(addr7, NODE_NONE)));
+ - + - ]
183 : :
184 : : // 6 addrs + 1 addr from last test = 7.
185 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(), 7U);
+ - ]
186 : :
187 : : // Select pulls from new and tried regardless of port number.
188 : 1 : std::set<uint16_t> ports;
189 [ + + ]: 21 : for (int i = 0; i < 20; ++i) {
190 [ + - + - : 40 : ports.insert(addrman->Select().first.GetPort());
+ - ]
191 : : }
192 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(ports.size(), 3U);
193 : 8 : }
194 : :
195 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(addrman_select_by_network)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
196 : : {
197 : 1 : auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
198 [ + - + - : 2 : BOOST_CHECK(!addrman->Select(/*new_only=*/true, NET_IPV4).first.IsValid());
+ - + - +
- ]
199 [ + - + - : 2 : BOOST_CHECK(!addrman->Select(/*new_only=*/false, NET_IPV4).first.IsValid());
+ - + - +
- ]
200 : :
201 : : // add ipv4 address to the new table
202 [ + - + - ]: 1 : CNetAddr source = ResolveIP("252.2.2.2");
203 [ + - + - ]: 1 : CService addr1 = ResolveService("250.1.1.1", 8333);
204 [ + - + - : 5 : BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
205 : :
206 [ + - + - : 2 : BOOST_CHECK(addrman->Select(/*new_only=*/true, NET_IPV4).first == addr1);
+ - + - +
- ]
207 [ + - + - : 2 : BOOST_CHECK(addrman->Select(/*new_only=*/false, NET_IPV4).first == addr1);
+ - + - +
- ]
208 [ + - + - : 2 : BOOST_CHECK(!addrman->Select(/*new_only=*/false, NET_IPV6).first.IsValid());
+ - + - +
- ]
209 [ + - + - : 2 : BOOST_CHECK(!addrman->Select(/*new_only=*/false, NET_ONION).first.IsValid());
+ - + - +
- ]
210 [ + - + - : 2 : BOOST_CHECK(!addrman->Select(/*new_only=*/false, NET_I2P).first.IsValid());
+ - + - +
- ]
211 [ + - + - : 2 : BOOST_CHECK(!addrman->Select(/*new_only=*/false, NET_CJDNS).first.IsValid());
+ - + - +
- ]
212 [ + - + - : 2 : BOOST_CHECK(!addrman->Select(/*new_only=*/true, NET_CJDNS).first.IsValid());
+ - + - +
- ]
213 [ + - + - : 2 : BOOST_CHECK(addrman->Select(/*new_only=*/false).first == addr1);
+ - + - +
- ]
214 : :
215 : : // add I2P address to the new table
216 [ + - ]: 1 : CAddress i2p_addr;
217 [ + - + - ]: 1 : i2p_addr.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p");
218 [ + - + - : 3 : BOOST_CHECK(addrman->Add({i2p_addr}, source));
+ - + - +
+ - - ]
219 : :
220 [ + - + - : 2 : BOOST_CHECK(addrman->Select(/*new_only=*/true, NET_I2P).first == i2p_addr);
+ - + - +
- ]
221 [ + - + - : 2 : BOOST_CHECK(addrman->Select(/*new_only=*/false, NET_I2P).first == i2p_addr);
+ - + - +
- ]
222 [ + - + - : 2 : BOOST_CHECK(addrman->Select(/*new_only=*/false, NET_IPV4).first == addr1);
+ - + - +
- ]
223 [ + - + - : 2 : BOOST_CHECK(!addrman->Select(/*new_only=*/false, NET_IPV6).first.IsValid());
+ - + - +
- ]
224 [ + - + - : 2 : BOOST_CHECK(!addrman->Select(/*new_only=*/false, NET_ONION).first.IsValid());
+ - + - +
- ]
225 [ + - + - : 2 : BOOST_CHECK(!addrman->Select(/*new_only=*/false, NET_CJDNS).first.IsValid());
+ - + - +
- ]
226 : :
227 : : // bump I2P address to tried table
228 [ + - + - : 2 : BOOST_CHECK(addrman->Good(i2p_addr));
+ - + - ]
229 : :
230 [ + - + - : 2 : BOOST_CHECK(!addrman->Select(/*new_only=*/true, NET_I2P).first.IsValid());
+ - + - +
- ]
231 [ + - + - : 2 : BOOST_CHECK(addrman->Select(/*new_only=*/false, NET_I2P).first == i2p_addr);
+ - + - +
- ]
232 : :
233 : : // add another I2P address to the new table
234 [ + - ]: 1 : CAddress i2p_addr2;
235 [ + - + - ]: 1 : i2p_addr2.SetSpecial("c4gfnttsuwqomiygupdqqqyy5y5emnk5c73hrfvatri67prd7vyq.b32.i2p");
236 [ + - + - : 3 : BOOST_CHECK(addrman->Add({i2p_addr2}, source));
+ - + - +
+ - - ]
237 : :
238 [ + - + - : 2 : BOOST_CHECK(addrman->Select(/*new_only=*/true, NET_I2P).first == i2p_addr2);
+ - + - ]
239 : :
240 : : // ensure that both new and tried table are selected from
241 : 1 : bool new_selected{false};
242 : 1 : bool tried_selected{false};
243 : 1 : int counter = 256;
244 : :
245 [ + - + + ]: 7 : while (--counter > 0 && (!new_selected || !tried_selected)) {
246 [ + - ]: 6 : const CAddress selected{addrman->Select(/*new_only=*/false, NET_I2P).first};
247 [ + - + - : 17 : BOOST_REQUIRE(selected == i2p_addr || selected == i2p_addr2);
+ + + - +
- + - +
- ]
248 [ + - + + ]: 6 : if (selected == i2p_addr) {
249 : : tried_selected = true;
250 : : } else {
251 : 5 : new_selected = true;
252 : : }
253 : 6 : }
254 : :
255 [ + - + - : 2 : BOOST_CHECK(new_selected);
+ - ]
256 [ + - + - ]: 2 : BOOST_CHECK(tried_selected);
257 : 4 : }
258 : :
259 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(addrman_select_special)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
260 : : {
261 : : // use a non-deterministic addrman to ensure a passing test isn't due to setup
262 : 1 : auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, /*deterministic=*/false, GetCheckRatio(m_node));
263 : :
264 [ + - + - ]: 1 : CNetAddr source = ResolveIP("252.2.2.2");
265 : :
266 : : // add I2P address to the tried table
267 [ + - ]: 1 : CAddress i2p_addr;
268 [ + - + - ]: 1 : i2p_addr.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p");
269 [ + - + - : 3 : BOOST_CHECK(addrman->Add({i2p_addr}, source));
+ - + - +
+ - - ]
270 [ + - + - : 2 : BOOST_CHECK(addrman->Good(i2p_addr));
+ - + - ]
271 : :
272 : : // add ipv4 address to the new table
273 [ + - + - ]: 1 : CService addr1 = ResolveService("250.1.1.3", 8333);
274 [ + - + - : 5 : BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
275 : :
276 : : // since the only ipv4 address is on the new table, ensure that the new
277 : : // table gets selected even if new_only is false. if the table was being
278 : : // selected at random, this test will sporadically fail
279 [ + - + - : 2 : BOOST_CHECK(addrman->Select(/*new_only=*/false, NET_IPV4).first == addr1);
+ - + - ]
280 : 3 : }
281 : :
282 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(addrman_new_collisions)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
283 : : {
284 : 1 : auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
285 : :
286 [ + - + - ]: 1 : CNetAddr source = ResolveIP("252.2.2.2");
287 : :
288 : 1 : uint32_t num_addrs{0};
289 : :
290 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(), num_addrs);
+ - ]
291 : :
292 [ + + ]: 23 : while (num_addrs < 22) { // Magic number! 250.1.1.1 - 250.1.1.22 do not collide with deterministic key = 1
293 [ + - + - : 44 : CService addr = ResolveService("250.1.1." + ToString(++num_addrs));
+ - ]
294 [ + - + - : 110 : BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
295 : :
296 : : // Test: No collision in new table yet.
297 [ + - + - : 22 : BOOST_CHECK_EQUAL(addrman->Size(), num_addrs);
+ - ]
298 : 22 : }
299 : :
300 : : // Test: new table collision!
301 [ + - + - : 2 : CService addr1 = ResolveService("250.1.1." + ToString(++num_addrs));
+ - ]
302 : 1 : uint32_t collisions{1};
303 [ + - + - : 5 : BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
304 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(), num_addrs - collisions);
+ - ]
305 : :
306 [ + - + - : 2 : CService addr2 = ResolveService("250.1.1." + ToString(++num_addrs));
+ - ]
307 [ + - + - : 5 : BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
308 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(), num_addrs - collisions);
+ - ]
309 : 25 : }
310 : :
311 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(addrman_new_multiplicity)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
312 : : {
313 : 1 : auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
314 [ + - + - ]: 1 : CAddress addr{CAddress(ResolveService("253.3.3.3", 8333), NODE_NONE)};
315 : 1 : const auto start_time{Now<NodeSeconds>()};
316 : 1 : addr.nTime = start_time;
317 : :
318 : : // test that multiplicity stays at 1 if nTime doesn't increase
319 [ + + ]: 20 : for (unsigned int i = 1; i < 20; ++i) {
320 [ + - + - : 57 : std::string addr_ip{ToString(i % 256) + "." + ToString(i >> 8 % 256) + ".1.1"};
+ - ]
321 [ + - ]: 19 : CNetAddr source{ResolveIP(addr_ip)};
322 [ + - + - : 38 : addrman->Add({addr}, source);
+ + - - ]
323 : 19 : }
324 [ + - ]: 1 : AddressPosition addr_pos = addrman->FindAddressEntry(addr).value();
325 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(addr_pos.multiplicity, 1U);
326 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(), 1U);
+ - ]
327 : :
328 : : // if nTime increases, an addr can occur in up to 8 buckets
329 : : // The acceptance probability decreases exponentially with existing multiplicity -
330 : : // choose number of iterations such that it gets to 8 with deterministic addrman.
331 [ + + ]: 400 : for (unsigned int i = 1; i < 400; ++i) {
332 [ + - + - : 1197 : std::string addr_ip{ToString(i % 256) + "." + ToString(i >> 8 % 256) + ".1.1"};
+ - ]
333 [ + - ]: 399 : CNetAddr source{ResolveIP(addr_ip)};
334 : 399 : addr.nTime = start_time + std::chrono::seconds{i};
335 [ + - + - : 798 : addrman->Add({addr}, source);
+ + - - ]
336 : 399 : }
337 [ + - ]: 1 : AddressPosition addr_pos_multi = addrman->FindAddressEntry(addr).value();
338 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(addr_pos_multi.multiplicity, 8U);
339 : : // multiplicity doesn't affect size
340 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(), 1U);
+ - ]
341 : 419 : }
342 : :
343 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
344 : : {
345 : 1 : auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
346 : :
347 [ + - + - ]: 1 : CNetAddr source = ResolveIP("252.2.2.2");
348 : :
349 : 1 : uint32_t num_addrs{0};
350 : :
351 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(), num_addrs);
+ - ]
352 : :
353 [ + + ]: 36 : while (num_addrs < 35) { // Magic number! 250.1.1.1 - 250.1.1.35 do not collide in tried with deterministic key = 1
354 [ + - + - : 70 : CService addr = ResolveService("250.1.1." + ToString(++num_addrs));
+ - ]
355 [ + - + - : 175 : BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
356 : :
357 : : // Test: Add to tried without collision
358 [ + - + - : 70 : BOOST_CHECK(addrman->Good(CAddress(addr, NODE_NONE)));
+ - ]
359 : :
360 : 35 : }
361 : :
362 : : // Test: Unable to add to tried table due to collision!
363 [ + - + - : 2 : CService addr1 = ResolveService("250.1.1." + ToString(++num_addrs));
+ - ]
364 [ + - + - : 5 : BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
365 [ + - + - : 2 : BOOST_CHECK(!addrman->Good(CAddress(addr1, NODE_NONE)));
+ - + - ]
366 : :
367 : : // Test: Add the next address to tried without collision
368 [ + - + - : 2 : CService addr2 = ResolveService("250.1.1." + ToString(++num_addrs));
+ - ]
369 [ + - + - : 5 : BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
370 [ + - + - : 2 : BOOST_CHECK(addrman->Good(CAddress(addr2, NODE_NONE)));
+ - ]
371 : 38 : }
372 : :
373 : :
374 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(addrman_getaddr)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
375 : : {
376 : 1 : auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
377 : :
378 : : // Test: Sanity check, GetAddr should never return anything if addrman
379 : : // is empty.
380 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(), 0U);
+ - ]
381 [ + - ]: 1 : std::vector<CAddress> vAddr1 = addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt);
382 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(vAddr1.size(), 0U);
383 : :
384 [ + - + - ]: 1 : CAddress addr1 = CAddress(ResolveService("250.250.2.1", 8333), NODE_NONE);
385 : 1 : addr1.nTime = Now<NodeSeconds>(); // Set time so isTerrible = false
386 [ + - + - ]: 1 : CAddress addr2 = CAddress(ResolveService("250.251.2.2", 9999), NODE_NONE);
387 : 1 : addr2.nTime = Now<NodeSeconds>();
388 [ + - + - ]: 1 : CAddress addr3 = CAddress(ResolveService("251.252.2.3", 8333), NODE_NONE);
389 : 1 : addr3.nTime = Now<NodeSeconds>();
390 [ + - + - ]: 1 : CAddress addr4 = CAddress(ResolveService("252.253.3.4", 8333), NODE_NONE);
391 : 1 : addr4.nTime = Now<NodeSeconds>();
392 [ + - + - ]: 1 : CAddress addr5 = CAddress(ResolveService("252.254.4.5", 8333), NODE_NONE);
393 : 1 : addr5.nTime = Now<NodeSeconds>();
394 [ + - + - ]: 1 : CNetAddr source1 = ResolveIP("250.1.2.1");
395 [ + - + - ]: 1 : CNetAddr source2 = ResolveIP("250.2.3.3");
396 : :
397 : : // Test: Ensure GetAddr works with new addresses.
398 [ + - + - : 6 : BOOST_CHECK(addrman->Add({addr1, addr3, addr5}, source1));
+ - + - +
+ - - ]
399 [ + - + - : 5 : BOOST_CHECK(addrman->Add({addr2, addr4}, source2));
+ - + - +
+ - - ]
400 : :
401 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt).size(), 5U);
+ - ]
402 : : // Net processing asks for 23% of addresses. 23% of 5 is 1 rounded down.
403 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/2500, /*max_pct=*/23, /*network=*/std::nullopt).size(), 1U);
+ - ]
404 : :
405 : : // Test: Ensure GetAddr works with new and tried addresses.
406 [ + - + - : 2 : BOOST_CHECK(addrman->Good(CAddress(addr1, NODE_NONE)));
+ - + - ]
407 [ + - + - : 2 : BOOST_CHECK(addrman->Good(CAddress(addr2, NODE_NONE)));
+ - + - ]
408 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt).size(), 5U);
+ - ]
409 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/2500, /*max_pct=*/23, /*network=*/std::nullopt).size(), 1U);
+ - ]
410 : :
411 : : // Test: Ensure GetAddr still returns 23% when addrman has many addrs.
412 [ + + ]: 2048 : for (unsigned int i = 1; i < (8 * 256); i++) {
413 : 2047 : int octet1 = i % 256;
414 : 2047 : int octet2 = i >> 8 % 256;
415 [ + - + - : 6141 : std::string strAddr = ToString(octet1) + "." + ToString(octet2) + ".1.23";
+ - ]
416 [ + - ]: 2047 : CAddress addr = CAddress(ResolveService(strAddr), NODE_NONE);
417 : :
418 : : // Ensure that for all addrs in addrman, isTerrible == false.
419 : 2047 : addr.nTime = Now<NodeSeconds>();
420 [ + - + - : 6141 : addrman->Add({addr}, ResolveIP(strAddr));
+ - + + -
- ]
421 [ + + ]: 2047 : if (i % 8 == 0)
422 [ + - ]: 255 : addrman->Good(addr);
423 : 2047 : }
424 [ + - ]: 1 : std::vector<CAddress> vAddr = addrman->GetAddr(/*max_addresses=*/2500, /*max_pct=*/23, /*network=*/std::nullopt);
425 : :
426 [ + - ]: 1 : size_t percent23 = (addrman->Size() * 23) / 100;
427 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(vAddr.size(), percent23);
428 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(vAddr.size(), 461U);
429 : : // (addrman.Size() < number of addresses added) due to address collisions.
430 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(), 2006U);
+ - ]
431 : 2050 : }
432 : :
433 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(getaddr_unfiltered)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
434 : : {
435 : 1 : auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
436 : :
437 : : // Set time on this addr so isTerrible = false
438 [ + - + - ]: 1 : CAddress addr1 = CAddress(ResolveService("250.250.2.1", 8333), NODE_NONE);
439 : 1 : addr1.nTime = Now<NodeSeconds>();
440 : : // Not setting time so this addr should be isTerrible = true
441 [ + - + - ]: 1 : CAddress addr2 = CAddress(ResolveService("250.251.2.2", 9999), NODE_NONE);
442 : :
443 [ + - + - ]: 1 : CNetAddr source = ResolveIP("250.1.2.1");
444 [ + - + - : 5 : BOOST_CHECK(addrman->Add({addr1, addr2}, source));
+ - + - +
+ - - ]
445 : :
446 : : // Filtered GetAddr should only return addr1
447 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt).size(), 1U);
+ - ]
448 : : // Unfiltered GetAddr should return addr1 and addr2
449 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt, /*filtered=*/false).size(), 2U);
+ - ]
450 : 2 : }
451 : :
452 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket_legacy)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
453 : : {
454 [ + - ]: 1 : CAddress addr1 = CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE);
455 [ + - + - ]: 1 : CAddress addr2 = CAddress(ResolveService("250.1.1.1", 9999), NODE_NONE);
456 : :
457 [ + - + - ]: 1 : CNetAddr source1 = ResolveIP("250.1.1.1");
458 : :
459 : :
460 : 1 : AddrInfo info1 = AddrInfo(addr1, source1);
461 : :
462 [ + - + - : 1 : uint256 nKey1 = (HashWriter{} << 1).GetHash();
+ - ]
463 [ + - + - : 1 : uint256 nKey2 = (HashWriter{} << 2).GetHash();
+ - ]
464 : :
465 [ + - + - : 1 : BOOST_CHECK_EQUAL(info1.GetTriedBucket(nKey1, EMPTY_NETGROUPMAN), 40);
+ - ]
466 : :
467 : : // Test: Make sure key actually randomizes bucket placement. A fail on
468 : : // this test could be a security issue.
469 [ + - + - : 2 : BOOST_CHECK(info1.GetTriedBucket(nKey1, EMPTY_NETGROUPMAN) != info1.GetTriedBucket(nKey2, EMPTY_NETGROUPMAN));
+ - + - ]
470 : :
471 : : // Test: Two addresses with same IP but different ports can map to
472 : : // different buckets because they have different keys.
473 : 1 : AddrInfo info2 = AddrInfo(addr2, source1);
474 : :
475 [ + - + - : 2 : BOOST_CHECK(info1.GetKey() != info2.GetKey());
+ - + - +
- ]
476 [ + - + - : 2 : BOOST_CHECK(info1.GetTriedBucket(nKey1, EMPTY_NETGROUPMAN) != info2.GetTriedBucket(nKey1, EMPTY_NETGROUPMAN));
+ - + - ]
477 : :
478 : 1 : std::set<int> buckets;
479 [ + + ]: 256 : for (int i = 0; i < 255; i++) {
480 : 255 : AddrInfo infoi = AddrInfo(
481 [ + - + - : 510 : CAddress(ResolveService("250.1.1." + ToString(i)), NODE_NONE),
+ - ]
482 [ + - + - : 765 : ResolveIP("250.1.1." + ToString(i)));
+ - ]
483 [ + - ]: 255 : int bucket = infoi.GetTriedBucket(nKey1, EMPTY_NETGROUPMAN);
484 [ + - ]: 255 : buckets.insert(bucket);
485 : 255 : }
486 : : // Test: IP addresses in the same /16 prefix should
487 : : // never get more than 8 buckets with legacy grouping
488 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(buckets.size(), 8U);
489 : :
490 : 1 : buckets.clear();
491 [ + + ]: 256 : for (int j = 0; j < 255; j++) {
492 : 255 : AddrInfo infoj = AddrInfo(
493 [ + - + - : 765 : CAddress(ResolveService("250." + ToString(j) + ".1.1"), NODE_NONE),
+ - ]
494 [ + - + - : 1020 : ResolveIP("250." + ToString(j) + ".1.1"));
+ - ]
495 [ + - ]: 255 : int bucket = infoj.GetTriedBucket(nKey1, EMPTY_NETGROUPMAN);
496 [ + - ]: 255 : buckets.insert(bucket);
497 : 255 : }
498 : : // Test: IP addresses in the different /16 prefix should map to more than
499 : : // 8 buckets with legacy grouping
500 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(buckets.size(), 160U);
501 : 3 : }
502 : :
503 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket_legacy)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
504 : : {
505 [ + - ]: 1 : CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
506 [ + - + - ]: 1 : CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE);
507 : :
508 [ + - + - ]: 1 : CNetAddr source1 = ResolveIP("250.1.2.1");
509 : :
510 : 1 : AddrInfo info1 = AddrInfo(addr1, source1);
511 : :
512 [ + - + - : 1 : uint256 nKey1 = (HashWriter{} << 1).GetHash();
+ - ]
513 [ + - + - : 1 : uint256 nKey2 = (HashWriter{} << 2).GetHash();
+ - ]
514 : :
515 : : // Test: Make sure the buckets are what we expect
516 [ + - + - : 1 : BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, EMPTY_NETGROUPMAN), 786);
+ - ]
517 [ + - + - : 1 : BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, source1, EMPTY_NETGROUPMAN), 786);
+ - ]
518 : :
519 : : // Test: Make sure key actually randomizes bucket placement. A fail on
520 : : // this test could be a security issue.
521 [ + - + - : 2 : BOOST_CHECK(info1.GetNewBucket(nKey1, EMPTY_NETGROUPMAN) != info1.GetNewBucket(nKey2, EMPTY_NETGROUPMAN));
+ - + - ]
522 : :
523 : : // Test: Ports should not affect bucket placement in the addr
524 : 1 : AddrInfo info2 = AddrInfo(addr2, source1);
525 [ + - + - : 2 : BOOST_CHECK(info1.GetKey() != info2.GetKey());
+ - + - +
- ]
526 [ + - + - : 1 : BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, EMPTY_NETGROUPMAN), info2.GetNewBucket(nKey1, EMPTY_NETGROUPMAN));
+ - + - ]
527 : :
528 : 1 : std::set<int> buckets;
529 [ + + ]: 256 : for (int i = 0; i < 255; i++) {
530 : 255 : AddrInfo infoi = AddrInfo(
531 [ + - + - : 510 : CAddress(ResolveService("250.1.1." + ToString(i)), NODE_NONE),
+ - ]
532 [ + - + - : 765 : ResolveIP("250.1.1." + ToString(i)));
+ - ]
533 [ + - ]: 255 : int bucket = infoi.GetNewBucket(nKey1, EMPTY_NETGROUPMAN);
534 [ + - ]: 255 : buckets.insert(bucket);
535 : 255 : }
536 : : // Test: IP addresses in the same group (\16 prefix for IPv4) should
537 : : // always map to the same bucket.
538 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(buckets.size(), 1U);
539 : :
540 : 1 : buckets.clear();
541 [ + + ]: 1021 : for (int j = 0; j < 4 * 255; j++) {
542 [ + - ]: 2040 : AddrInfo infoj = AddrInfo(CAddress(
543 : 1020 : ResolveService(
544 [ + - + - : 4080 : ToString(250 + (j / 255)) + "." + ToString(j % 256) + ".1.1"), NODE_NONE),
+ - + - ]
545 [ + - + - ]: 3060 : ResolveIP("251.4.1.1"));
546 [ + - ]: 1020 : int bucket = infoj.GetNewBucket(nKey1, EMPTY_NETGROUPMAN);
547 [ + - ]: 1020 : buckets.insert(bucket);
548 : 1020 : }
549 : : // Test: IP addresses in the same source groups should map to NO MORE
550 : : // than 64 buckets.
551 [ + - + - ]: 2 : BOOST_CHECK(buckets.size() <= 64);
552 : :
553 : 1 : buckets.clear();
554 [ + + ]: 256 : for (int p = 0; p < 255; p++) {
555 : 255 : AddrInfo infoj = AddrInfo(
556 [ + - + - ]: 510 : CAddress(ResolveService("250.1.1.1"), NODE_NONE),
557 [ + - + - : 1020 : ResolveIP("250." + ToString(p) + ".1.1"));
+ - ]
558 [ + - ]: 255 : int bucket = infoj.GetNewBucket(nKey1, EMPTY_NETGROUPMAN);
559 [ + - ]: 255 : buckets.insert(bucket);
560 : 255 : }
561 : : // Test: IP addresses in the different source groups should map to MORE
562 : : // than 64 buckets.
563 [ + - + - ]: 2 : BOOST_CHECK(buckets.size() > 64);
564 : 3 : }
565 : :
566 : : // The following three test cases use asmap.raw
567 : : // We use an artificial minimal mock mapping
568 : : // 250.0.0.0/8 AS1000
569 : : // 101.1.0.0/16 AS1
570 : : // 101.2.0.0/16 AS2
571 : : // 101.3.0.0/16 AS3
572 : : // 101.4.0.0/16 AS4
573 : : // 101.5.0.0/16 AS5
574 : : // 101.6.0.0/16 AS6
575 : : // 101.7.0.0/16 AS7
576 : : // 101.8.0.0/16 AS8
577 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
578 : : {
579 : 1 : std::vector<bool> asmap = FromBytes(asmap_raw, sizeof(asmap_raw) * 8);
580 [ + - ]: 2 : NetGroupManager ngm_asmap{asmap};
581 : :
582 [ + - + - ]: 1 : CAddress addr1 = CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE);
583 [ + - + - ]: 1 : CAddress addr2 = CAddress(ResolveService("250.1.1.1", 9999), NODE_NONE);
584 : :
585 [ + - + - ]: 1 : CNetAddr source1 = ResolveIP("250.1.1.1");
586 : :
587 : :
588 : 1 : AddrInfo info1 = AddrInfo(addr1, source1);
589 : :
590 [ + - + - : 1 : uint256 nKey1 = (HashWriter{} << 1).GetHash();
+ - ]
591 [ + - + - : 1 : uint256 nKey2 = (HashWriter{} << 2).GetHash();
+ - ]
592 : :
593 [ + - + - : 1 : BOOST_CHECK_EQUAL(info1.GetTriedBucket(nKey1, ngm_asmap), 236);
+ - ]
594 : :
595 : : // Test: Make sure key actually randomizes bucket placement. A fail on
596 : : // this test could be a security issue.
597 [ + - + - : 2 : BOOST_CHECK(info1.GetTriedBucket(nKey1, ngm_asmap) != info1.GetTriedBucket(nKey2, ngm_asmap));
+ - + - ]
598 : :
599 : : // Test: Two addresses with same IP but different ports can map to
600 : : // different buckets because they have different keys.
601 : 1 : AddrInfo info2 = AddrInfo(addr2, source1);
602 : :
603 [ + - + - : 2 : BOOST_CHECK(info1.GetKey() != info2.GetKey());
+ - + - +
- ]
604 [ + - + - : 2 : BOOST_CHECK(info1.GetTriedBucket(nKey1, ngm_asmap) != info2.GetTriedBucket(nKey1, ngm_asmap));
+ - + - ]
605 : :
606 : 1 : std::set<int> buckets;
607 [ + + ]: 256 : for (int j = 0; j < 255; j++) {
608 : 255 : AddrInfo infoj = AddrInfo(
609 [ + - + - : 765 : CAddress(ResolveService("101." + ToString(j) + ".1.1"), NODE_NONE),
+ - ]
610 [ + - + - : 1020 : ResolveIP("101." + ToString(j) + ".1.1"));
+ - ]
611 [ + - ]: 255 : int bucket = infoj.GetTriedBucket(nKey1, ngm_asmap);
612 [ + - ]: 255 : buckets.insert(bucket);
613 : 255 : }
614 : : // Test: IP addresses in the different /16 prefix MAY map to more than
615 : : // 8 buckets.
616 [ + - + - ]: 2 : BOOST_CHECK(buckets.size() > 8);
617 : :
618 : 1 : buckets.clear();
619 [ + + ]: 256 : for (int j = 0; j < 255; j++) {
620 : 255 : AddrInfo infoj = AddrInfo(
621 [ + - + - : 765 : CAddress(ResolveService("250." + ToString(j) + ".1.1"), NODE_NONE),
+ - ]
622 [ + - + - : 1020 : ResolveIP("250." + ToString(j) + ".1.1"));
+ - ]
623 [ + - ]: 255 : int bucket = infoj.GetTriedBucket(nKey1, ngm_asmap);
624 [ + - ]: 255 : buckets.insert(bucket);
625 : 255 : }
626 : : // Test: IP addresses in the different /16 prefix MAY NOT map to more than
627 : : // 8 buckets.
628 [ + - + - ]: 2 : BOOST_CHECK(buckets.size() == 8);
629 : 3 : }
630 : :
631 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
632 : : {
633 : 1 : std::vector<bool> asmap = FromBytes(asmap_raw, sizeof(asmap_raw) * 8);
634 [ + - ]: 2 : NetGroupManager ngm_asmap{asmap};
635 : :
636 [ + - + - ]: 1 : CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
637 [ + - + - ]: 1 : CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE);
638 : :
639 [ + - + - ]: 1 : CNetAddr source1 = ResolveIP("250.1.2.1");
640 : :
641 : 1 : AddrInfo info1 = AddrInfo(addr1, source1);
642 : :
643 [ + - + - : 1 : uint256 nKey1 = (HashWriter{} << 1).GetHash();
+ - ]
644 [ + - + - : 1 : uint256 nKey2 = (HashWriter{} << 2).GetHash();
+ - ]
645 : :
646 : : // Test: Make sure the buckets are what we expect
647 [ + - + - : 1 : BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, ngm_asmap), 795);
+ - ]
648 [ + - + - : 1 : BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, source1, ngm_asmap), 795);
+ - ]
649 : :
650 : : // Test: Make sure key actually randomizes bucket placement. A fail on
651 : : // this test could be a security issue.
652 [ + - + - : 2 : BOOST_CHECK(info1.GetNewBucket(nKey1, ngm_asmap) != info1.GetNewBucket(nKey2, ngm_asmap));
+ - + - ]
653 : :
654 : : // Test: Ports should not affect bucket placement in the addr
655 : 1 : AddrInfo info2 = AddrInfo(addr2, source1);
656 [ + - + - : 2 : BOOST_CHECK(info1.GetKey() != info2.GetKey());
+ - + - +
- ]
657 [ + - + - : 1 : BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, ngm_asmap), info2.GetNewBucket(nKey1, ngm_asmap));
+ - + - ]
658 : :
659 : 1 : std::set<int> buckets;
660 [ + + ]: 256 : for (int i = 0; i < 255; i++) {
661 : 255 : AddrInfo infoi = AddrInfo(
662 [ + - + - : 510 : CAddress(ResolveService("250.1.1." + ToString(i)), NODE_NONE),
+ - ]
663 [ + - + - : 765 : ResolveIP("250.1.1." + ToString(i)));
+ - ]
664 [ + - ]: 255 : int bucket = infoi.GetNewBucket(nKey1, ngm_asmap);
665 [ + - ]: 255 : buckets.insert(bucket);
666 : 255 : }
667 : : // Test: IP addresses in the same /16 prefix
668 : : // usually map to the same bucket.
669 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(buckets.size(), 1U);
670 : :
671 : 1 : buckets.clear();
672 [ + + ]: 1021 : for (int j = 0; j < 4 * 255; j++) {
673 [ + - ]: 2040 : AddrInfo infoj = AddrInfo(CAddress(
674 : 1020 : ResolveService(
675 [ + - + - : 4080 : ToString(250 + (j / 255)) + "." + ToString(j % 256) + ".1.1"), NODE_NONE),
+ - + - ]
676 [ + - + - ]: 3060 : ResolveIP("251.4.1.1"));
677 [ + - ]: 1020 : int bucket = infoj.GetNewBucket(nKey1, ngm_asmap);
678 [ + - ]: 1020 : buckets.insert(bucket);
679 : 1020 : }
680 : : // Test: IP addresses in the same source /16 prefix should not map to more
681 : : // than 64 buckets.
682 [ + - + - ]: 2 : BOOST_CHECK(buckets.size() <= 64);
683 : :
684 : 1 : buckets.clear();
685 [ + + ]: 256 : for (int p = 0; p < 255; p++) {
686 : 255 : AddrInfo infoj = AddrInfo(
687 [ + - + - ]: 510 : CAddress(ResolveService("250.1.1.1"), NODE_NONE),
688 [ + - + - : 1020 : ResolveIP("101." + ToString(p) + ".1.1"));
+ - ]
689 [ + - ]: 255 : int bucket = infoj.GetNewBucket(nKey1, ngm_asmap);
690 [ + - ]: 255 : buckets.insert(bucket);
691 : 255 : }
692 : : // Test: IP addresses in the different source /16 prefixes usually map to MORE
693 : : // than 1 bucket.
694 [ + - + - ]: 2 : BOOST_CHECK(buckets.size() > 1);
695 : :
696 : 1 : buckets.clear();
697 [ + + ]: 256 : for (int p = 0; p < 255; p++) {
698 : 255 : AddrInfo infoj = AddrInfo(
699 [ + - + - ]: 510 : CAddress(ResolveService("250.1.1.1"), NODE_NONE),
700 [ + - + - : 1020 : ResolveIP("250." + ToString(p) + ".1.1"));
+ - ]
701 [ + - ]: 255 : int bucket = infoj.GetNewBucket(nKey1, ngm_asmap);
702 [ + - ]: 255 : buckets.insert(bucket);
703 : 255 : }
704 : : // Test: IP addresses in the different source /16 prefixes sometimes map to NO MORE
705 : : // than 1 bucket.
706 [ + - + - ]: 2 : BOOST_CHECK(buckets.size() == 1);
707 : 3 : }
708 : :
709 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(addrman_serialization)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
710 : : {
711 : 1 : std::vector<bool> asmap1 = FromBytes(asmap_raw, sizeof(asmap_raw) * 8);
712 [ + - ]: 2 : NetGroupManager netgroupman{asmap1};
713 : :
714 [ + - ]: 1 : const auto ratio = GetCheckRatio(m_node);
715 [ + - ]: 1 : auto addrman_asmap1 = std::make_unique<AddrMan>(netgroupman, DETERMINISTIC, ratio);
716 [ + - ]: 1 : auto addrman_asmap1_dup = std::make_unique<AddrMan>(netgroupman, DETERMINISTIC, ratio);
717 [ + - ]: 1 : auto addrman_noasmap = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, ratio);
718 : :
719 : 1 : DataStream stream{};
720 : :
721 [ + - + - ]: 1 : CAddress addr = CAddress(ResolveService("250.1.1.1"), NODE_NONE);
722 [ + - ]: 1 : CNetAddr default_source;
723 : :
724 [ + - + - : 2 : addrman_asmap1->Add({addr}, default_source);
+ + - - ]
725 : :
726 [ + - ]: 1 : stream << *addrman_asmap1;
727 : : // serizalizing/deserializing addrman with the same asmap
728 [ + - ]: 1 : stream >> *addrman_asmap1_dup;
729 : :
730 [ + - ]: 1 : AddressPosition addr_pos1 = addrman_asmap1->FindAddressEntry(addr).value();
731 [ + - ]: 1 : AddressPosition addr_pos2 = addrman_asmap1_dup->FindAddressEntry(addr).value();
732 [ + - + - : 2 : BOOST_CHECK(addr_pos1.multiplicity != 0);
+ - ]
733 [ + - + - : 2 : BOOST_CHECK(addr_pos2.multiplicity != 0);
+ - ]
734 : :
735 [ + - + - : 2 : BOOST_CHECK(addr_pos1 == addr_pos2);
+ - ]
736 : :
737 : : // deserializing asmaped peers.dat to non-asmaped addrman
738 [ + - ]: 1 : stream << *addrman_asmap1;
739 [ + - ]: 1 : stream >> *addrman_noasmap;
740 [ + - ]: 1 : AddressPosition addr_pos3 = addrman_noasmap->FindAddressEntry(addr).value();
741 [ + - + - : 2 : BOOST_CHECK(addr_pos3.multiplicity != 0);
+ - ]
742 [ + - + - : 2 : BOOST_CHECK(addr_pos1.bucket != addr_pos3.bucket);
+ - ]
743 [ + - + - : 2 : BOOST_CHECK(addr_pos1.position != addr_pos3.position);
+ - ]
744 : :
745 : : // deserializing non-asmaped peers.dat to asmaped addrman
746 [ + - ]: 2 : addrman_asmap1 = std::make_unique<AddrMan>(netgroupman, DETERMINISTIC, ratio);
747 [ + - ]: 2 : addrman_noasmap = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, ratio);
748 [ + - + - : 2 : addrman_noasmap->Add({addr}, default_source);
+ + - - ]
749 [ + - ]: 1 : stream << *addrman_noasmap;
750 [ + - ]: 1 : stream >> *addrman_asmap1;
751 : :
752 [ + - ]: 1 : AddressPosition addr_pos4 = addrman_asmap1->FindAddressEntry(addr).value();
753 [ + - + - : 2 : BOOST_CHECK(addr_pos4.multiplicity != 0);
+ - ]
754 [ + - + - : 2 : BOOST_CHECK(addr_pos4.bucket != addr_pos3.bucket);
+ - ]
755 [ + - + - : 2 : BOOST_CHECK(addr_pos4 == addr_pos2);
+ - ]
756 : :
757 : : // used to map to different buckets, now maps to the same bucket.
758 [ + - ]: 2 : addrman_asmap1 = std::make_unique<AddrMan>(netgroupman, DETERMINISTIC, ratio);
759 [ + - ]: 2 : addrman_noasmap = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, ratio);
760 [ + - + - ]: 1 : CAddress addr1 = CAddress(ResolveService("250.1.1.1"), NODE_NONE);
761 [ + - + - ]: 1 : CAddress addr2 = CAddress(ResolveService("250.2.1.1"), NODE_NONE);
762 [ + - + - : 4 : addrman_noasmap->Add({addr, addr2}, default_source);
+ + - - ]
763 [ + - ]: 1 : AddressPosition addr_pos5 = addrman_noasmap->FindAddressEntry(addr1).value();
764 [ + - ]: 1 : AddressPosition addr_pos6 = addrman_noasmap->FindAddressEntry(addr2).value();
765 [ + - + - : 2 : BOOST_CHECK(addr_pos5.bucket != addr_pos6.bucket);
+ - ]
766 [ + - ]: 1 : stream << *addrman_noasmap;
767 [ + - ]: 1 : stream >> *addrman_asmap1;
768 [ + - ]: 1 : AddressPosition addr_pos7 = addrman_asmap1->FindAddressEntry(addr1).value();
769 [ + - ]: 1 : AddressPosition addr_pos8 = addrman_asmap1->FindAddressEntry(addr2).value();
770 [ + - + - : 2 : BOOST_CHECK(addr_pos7.bucket == addr_pos8.bucket);
+ - ]
771 [ + - + - ]: 2 : BOOST_CHECK(addr_pos7.position != addr_pos8.position);
772 : 4 : }
773 : :
774 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(remove_invalid)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
775 : : {
776 : : // Confirm that invalid addresses are ignored in unserialization.
777 : :
778 : 1 : auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
779 : 1 : DataStream stream{};
780 : :
781 [ + - + - ]: 1 : const CAddress new1{ResolveService("5.5.5.5"), NODE_NONE};
782 [ + - + - ]: 1 : const CAddress new2{ResolveService("6.6.6.6"), NODE_NONE};
783 [ + - + - ]: 1 : const CAddress tried1{ResolveService("7.7.7.7"), NODE_NONE};
784 [ + - + - ]: 1 : const CAddress tried2{ResolveService("8.8.8.8"), NODE_NONE};
785 : :
786 [ + - + - : 6 : addrman->Add({new1, tried1, new2, tried2}, CNetAddr{});
+ - + + -
- ]
787 [ + - ]: 1 : addrman->Good(tried1);
788 [ + - ]: 1 : addrman->Good(tried2);
789 [ + - + - : 1 : BOOST_REQUIRE_EQUAL(addrman->Size(), 4);
+ - ]
790 : :
791 [ + - ]: 1 : stream << *addrman;
792 : :
793 [ + - ]: 1 : const std::string str{stream.str()};
794 : 1 : size_t pos;
795 : :
796 : 1 : const char new2_raw[]{6, 6, 6, 6};
797 : 1 : const uint8_t new2_raw_replacement[]{0, 0, 0, 0}; // 0.0.0.0 is !IsValid()
798 : 1 : pos = str.find(new2_raw, 0, sizeof(new2_raw));
799 [ + - + - : 2 : BOOST_REQUIRE(pos != std::string::npos);
+ - ]
800 [ + - + - ]: 2 : BOOST_REQUIRE(pos + sizeof(new2_raw_replacement) <= stream.size());
801 : 1 : memcpy(stream.data() + pos, new2_raw_replacement, sizeof(new2_raw_replacement));
802 : :
803 : 1 : const char tried2_raw[]{8, 8, 8, 8};
804 : 1 : const uint8_t tried2_raw_replacement[]{255, 255, 255, 255}; // 255.255.255.255 is !IsValid()
805 : 1 : pos = str.find(tried2_raw, 0, sizeof(tried2_raw));
806 [ + - + - : 2 : BOOST_REQUIRE(pos != std::string::npos);
+ - ]
807 [ + - + - : 2 : BOOST_REQUIRE(pos + sizeof(tried2_raw_replacement) <= stream.size());
+ - ]
808 [ + - ]: 1 : memcpy(stream.data() + pos, tried2_raw_replacement, sizeof(tried2_raw_replacement));
809 : :
810 [ + - + - ]: 2 : addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
811 [ + - ]: 1 : stream >> *addrman;
812 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(), 2);
+ - ]
813 : 2 : }
814 : :
815 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(addrman_selecttriedcollision)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
816 : : {
817 : 1 : auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
818 : :
819 [ + - + - : 2 : BOOST_CHECK(addrman->Size() == 0);
+ - + - ]
820 : :
821 : : // Empty addrman should return blank addrman info.
822 [ + - + - : 2 : BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
+ - + - +
- ]
823 : :
824 : : // Add twenty two addresses.
825 [ + - + - ]: 1 : CNetAddr source = ResolveIP("252.2.2.2");
826 [ + + ]: 23 : for (unsigned int i = 1; i < 23; i++) {
827 [ + - + - : 44 : CService addr = ResolveService("250.1.1." + ToString(i));
+ - ]
828 [ + - + - : 110 : BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
829 : :
830 : : // No collisions in tried.
831 [ + - + - : 44 : BOOST_CHECK(addrman->Good(addr));
+ - + - ]
832 [ + - + - : 44 : BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
+ - + - ]
833 : 22 : }
834 : :
835 : : // Ensure Good handles duplicates well.
836 : : // If an address is a duplicate, Good will return false but will not count it as a collision.
837 [ + + ]: 23 : for (unsigned int i = 1; i < 23; i++) {
838 [ + - + - : 44 : CService addr = ResolveService("250.1.1." + ToString(i));
+ - ]
839 : :
840 : : // Unable to add duplicate address to tried table.
841 [ + - + - : 44 : BOOST_CHECK(!addrman->Good(addr));
+ - + - ]
842 : :
843 : : // Verify duplicate address not marked as a collision.
844 [ + - + - : 44 : BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
+ - + - ]
845 : 22 : }
846 : 23 : }
847 : :
848 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(addrman_noevict)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
849 : : {
850 : 1 : auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
851 : :
852 : : // Add 35 addresses.
853 [ + - + - ]: 1 : CNetAddr source = ResolveIP("252.2.2.2");
854 [ + + ]: 36 : for (unsigned int i = 1; i < 36; i++) {
855 [ + - + - : 70 : CService addr = ResolveService("250.1.1." + ToString(i));
+ - ]
856 [ + - + - : 175 : BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
857 : :
858 : : // No collision yet.
859 [ + - + - : 70 : BOOST_CHECK(addrman->Good(addr));
+ - ]
860 : 35 : }
861 : :
862 : : // Collision in tried table between 36 and 19.
863 [ + - + - ]: 1 : CService addr36 = ResolveService("250.1.1.36");
864 [ + - + - : 5 : BOOST_CHECK(addrman->Add({CAddress(addr36, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
865 [ + - + - : 2 : BOOST_CHECK(!addrman->Good(addr36));
+ - + - ]
866 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->SelectTriedCollision().first.ToStringAddrPort(), "250.1.1.19:0");
+ - + - ]
867 : :
868 : : // 36 should be discarded and 19 not evicted.
869 : : // This means we keep 19 in the tried table and
870 : : // 36 stays in the new table.
871 [ + - ]: 1 : addrman->ResolveCollisions();
872 [ + - + - : 2 : BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
+ - + - ]
873 : :
874 : : // Lets create two collisions.
875 [ + + ]: 23 : for (unsigned int i = 37; i < 59; i++) {
876 [ + - + - : 44 : CService addr = ResolveService("250.1.1." + ToString(i));
+ - ]
877 [ + - + - : 110 : BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
878 [ + - + - : 44 : BOOST_CHECK(addrman->Good(addr));
+ - ]
879 : 22 : }
880 : :
881 : : // Cause a collision in the tried table.
882 [ + - + - ]: 1 : CService addr59 = ResolveService("250.1.1.59");
883 [ + - + - : 5 : BOOST_CHECK(addrman->Add({CAddress(addr59, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
884 [ + - + - : 2 : BOOST_CHECK(!addrman->Good(addr59));
+ - + - ]
885 : :
886 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->SelectTriedCollision().first.ToStringAddrPort(), "250.1.1.10:0");
+ - + - ]
887 : :
888 : : // Cause a second collision in the new table.
889 [ + - + - : 5 : BOOST_CHECK(!addrman->Add({CAddress(addr36, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
890 : :
891 : : // 36 still cannot be moved from new to tried due to colliding with 19
892 [ + - + - : 2 : BOOST_CHECK(!addrman->Good(addr36));
+ - + - ]
893 [ + - + - : 2 : BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() != "[::]:0");
+ - + - +
- ]
894 : :
895 : : // Resolve all collisions.
896 [ + - ]: 1 : addrman->ResolveCollisions();
897 [ + - + - : 2 : BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
+ - + - ]
898 : 61 : }
899 : :
900 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(addrman_evictionworks)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
901 : : {
902 : 1 : auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
903 : :
904 [ + - + - : 2 : BOOST_CHECK(addrman->Size() == 0);
+ - + - ]
905 : :
906 : : // Empty addrman should return blank addrman info.
907 [ + - + - : 2 : BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
+ - + - +
- ]
908 : :
909 : : // Add 35 addresses
910 [ + - + - ]: 1 : CNetAddr source = ResolveIP("252.2.2.2");
911 [ + + ]: 36 : for (unsigned int i = 1; i < 36; i++) {
912 [ + - + - : 70 : CService addr = ResolveService("250.1.1." + ToString(i));
+ - ]
913 [ + - + - : 175 : BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
914 : :
915 : : // No collision yet.
916 [ + - + - : 70 : BOOST_CHECK(addrman->Good(addr));
+ - ]
917 : 35 : }
918 : :
919 : : // Collision between 36 and 19.
920 [ + - + - ]: 1 : CService addr = ResolveService("250.1.1.36");
921 [ + - + - : 5 : BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
+ - + - +
+ + - -
- ]
922 [ + - + - : 2 : BOOST_CHECK(!addrman->Good(addr));
+ - + - ]
923 : :
924 [ + - ]: 1 : auto info = addrman->SelectTriedCollision().first;
925 [ + - + - : 1 : BOOST_CHECK_EQUAL(info.ToStringAddrPort(), "250.1.1.19:0");
+ - ]
926 : :
927 : : // Ensure test of address fails, so that it is evicted.
928 : : // Update entry in tried by setting last good connection in the deep past.
929 [ + - + - : 2 : BOOST_CHECK(!addrman->Good(info, NodeSeconds{1s}));
+ - ]
930 [ + - ]: 1 : addrman->Attempt(info, /*fCountFailure=*/false, Now<NodeSeconds>() - 61s);
931 : :
932 : : // Should swap 36 for 19.
933 [ + - ]: 1 : addrman->ResolveCollisions();
934 [ + - + - : 2 : BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
+ - + - ]
935 [ + - ]: 2 : AddressPosition addr_pos{addrman->FindAddressEntry(CAddress(addr, NODE_NONE)).value()};
936 [ + - + - : 2 : BOOST_CHECK(addr_pos.tried);
+ - ]
937 : :
938 : : // If 36 was swapped for 19, then adding 36 to tried should fail because we
939 : : // are attempting to add a duplicate.
940 : : // We check this by verifying Good() returns false and also verifying that
941 : : // we have no collisions.
942 [ + - + - : 2 : BOOST_CHECK(!addrman->Good(addr));
+ - + - ]
943 [ + - + - : 2 : BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
+ - + - +
- ]
944 : :
945 : : // 19 should fail as a collision (not a duplicate) if we now attempt to move
946 : : // it to the tried table.
947 [ + - + - ]: 1 : CService addr19 = ResolveService("250.1.1.19");
948 [ + - + - : 2 : BOOST_CHECK(!addrman->Good(addr19));
+ - + - ]
949 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->SelectTriedCollision().first.ToStringAddrPort(), "250.1.1.36:0");
+ - + - ]
950 : :
951 : : // Eviction is also successful if too much time has passed since last try
952 [ + - + - ]: 1 : SetMockTime(GetTime() + 4 * 60 *60);
953 [ + - ]: 1 : addrman->ResolveCollisions();
954 [ + - + - : 2 : BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
+ - + - ]
955 : : //Now 19 is in tried again, and 36 back to new
956 [ + - ]: 2 : AddressPosition addr_pos19{addrman->FindAddressEntry(CAddress(addr19, NODE_NONE)).value()};
957 [ + - + - ]: 2 : BOOST_CHECK(addr_pos19.tried);
958 [ + - ]: 2 : AddressPosition addr_pos36{addrman->FindAddressEntry(CAddress(addr, NODE_NONE)).value()};
959 [ + - + - ]: 2 : BOOST_CHECK(!addr_pos36.tried);
960 : 37 : }
961 : :
962 : 2 : static auto AddrmanToStream(const AddrMan& addrman)
963 : : {
964 : 2 : DataStream ssPeersIn{};
965 [ + - + - ]: 2 : ssPeersIn << Params().MessageStart();
966 [ + - ]: 2 : ssPeersIn << addrman;
967 : 2 : return ssPeersIn;
968 : 0 : }
969 : :
970 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(load_addrman)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
971 : : {
972 : 1 : AddrMan addrman{EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node)};
973 : :
974 : 1 : std::optional<CService> addr1, addr2, addr3, addr4;
975 [ + - + - : 2 : addr1 = Lookup("250.7.1.1", 8333, false);
+ - ]
976 [ + - + - : 2 : BOOST_CHECK(addr1.has_value());
+ - ]
977 [ + - + - : 2 : addr2 = Lookup("250.7.2.2", 9999, false);
+ - ]
978 [ + - + - : 2 : BOOST_CHECK(addr2.has_value());
+ - ]
979 [ + - + - : 2 : addr3 = Lookup("250.7.3.3", 9999, false);
+ - ]
980 [ + - + - : 2 : BOOST_CHECK(addr3.has_value());
+ - ]
981 [ + - + - ]: 3 : addr3 = Lookup("250.7.3.3"s, 9999, false);
982 [ + - + - : 2 : BOOST_CHECK(addr3.has_value());
+ - ]
983 [ + - + - ]: 3 : addr4 = Lookup("250.7.3.3\0example.com"s, 9999, false);
984 [ + - + - : 2 : BOOST_CHECK(!addr4.has_value());
+ - ]
985 : :
986 : : // Add three addresses to new table.
987 [ + - + - : 2 : const std::optional<CService> source{Lookup("252.5.1.1", 8333, false)};
+ - ]
988 [ + - + - : 2 : BOOST_CHECK(source.has_value());
+ - ]
989 [ - + + + : 8 : std::vector<CAddress> addresses{CAddress(addr1.value(), NODE_NONE), CAddress(addr2.value(), NODE_NONE), CAddress(addr3.value(), NODE_NONE)};
- - ]
990 [ + - + - : 2 : BOOST_CHECK(addrman.Add(addresses, source.value()));
+ - + - +
- ]
991 [ + - + - : 2 : BOOST_CHECK(addrman.Size() == 3);
+ - + - ]
992 : :
993 : : // Test that the de-serialization does not throw an exception.
994 [ + - ]: 1 : auto ssPeers1{AddrmanToStream(addrman)};
995 : 1 : bool exceptionThrown = false;
996 [ + - + - ]: 1 : AddrMan addrman1{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};
997 : :
998 [ + - + - : 2 : BOOST_CHECK(addrman1.Size() == 0);
+ - + - ]
999 : 1 : try {
1000 : 1 : unsigned char pchMsgTmp[4];
1001 [ + - ]: 1 : ssPeers1 >> pchMsgTmp;
1002 [ + - ]: 1 : ssPeers1 >> addrman1;
1003 [ - - ]: 0 : } catch (const std::exception&) {
1004 : 0 : exceptionThrown = true;
1005 : 0 : }
1006 : :
1007 [ + - + - : 2 : BOOST_CHECK(addrman1.Size() == 3);
+ - + - ]
1008 [ + - + - : 2 : BOOST_CHECK(exceptionThrown == false);
+ - ]
1009 : :
1010 : : // Test that ReadFromStream creates an addrman with the correct number of addrs.
1011 [ + - ]: 1 : DataStream ssPeers2 = AddrmanToStream(addrman);
1012 : :
1013 [ + - + - ]: 1 : AddrMan addrman2{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};
1014 [ + - + - : 2 : BOOST_CHECK(addrman2.Size() == 0);
+ - + - ]
1015 [ + - ]: 1 : ReadFromStream(addrman2, ssPeers2);
1016 [ + - + - : 2 : BOOST_CHECK(addrman2.Size() == 3);
+ - ]
1017 [ + - + - : 5 : }
+ - - - ]
1018 : :
1019 : : // Produce a corrupt peers.dat that claims 20 addrs when it only has one addr.
1020 : 2 : static auto MakeCorruptPeersDat()
1021 : : {
1022 : 2 : DataStream s{};
1023 [ + - + - ]: 2 : s << ::Params().MessageStart();
1024 : :
1025 : 2 : unsigned char nVersion = 1;
1026 [ + - ]: 2 : s << nVersion;
1027 [ + - ]: 2 : s << ((unsigned char)32);
1028 [ + - ]: 2 : s << uint256::ONE;
1029 [ + - ]: 2 : s << 10; // nNew
1030 [ + - ]: 2 : s << 10; // nTried
1031 : :
1032 : 2 : int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
1033 [ + - ]: 2 : s << nUBuckets;
1034 : :
1035 [ + - + - : 4 : const std::optional<CService> serv{Lookup("252.1.1.1", 7777, false)};
+ - ]
1036 [ + - + - : 4 : BOOST_REQUIRE(serv.has_value());
+ - ]
1037 [ + - ]: 2 : CAddress addr = CAddress(serv.value(), NODE_NONE);
1038 [ + - + - : 4 : std::optional<CNetAddr> resolved{LookupHost("252.2.2.2", false)};
+ - ]
1039 [ + - + - : 4 : BOOST_REQUIRE(resolved.has_value());
+ - ]
1040 [ + - ]: 2 : AddrInfo info = AddrInfo(addr, resolved.value());
1041 [ + - ]: 2 : s << CAddress::V1_DISK(info);
1042 : :
1043 : 2 : return s;
1044 : 2 : }
1045 : :
1046 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(load_addrman_corrupted)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
1047 : : {
1048 : : // Test that the de-serialization of corrupted peers.dat throws an exception.
1049 : 1 : auto ssPeers1{MakeCorruptPeersDat()};
1050 : 1 : bool exceptionThrown = false;
1051 [ + - + - ]: 1 : AddrMan addrman1{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};
1052 [ + - + - : 2 : BOOST_CHECK(addrman1.Size() == 0);
+ - + - ]
1053 : 1 : try {
1054 : 1 : unsigned char pchMsgTmp[4];
1055 [ + - ]: 1 : ssPeers1 >> pchMsgTmp;
1056 [ - + ]: 1 : ssPeers1 >> addrman1;
1057 [ - + ]: 1 : } catch (const std::exception&) {
1058 : 1 : exceptionThrown = true;
1059 : 1 : }
1060 [ + - + - : 2 : BOOST_CHECK(exceptionThrown);
+ - ]
1061 : :
1062 : : // Test that ReadFromStream fails if peers.dat is corrupt
1063 [ + - ]: 1 : auto ssPeers2{MakeCorruptPeersDat()};
1064 : :
1065 [ + - + - ]: 1 : AddrMan addrman2{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};
1066 [ + - + - : 2 : BOOST_CHECK(addrman2.Size() == 0);
+ - + - ]
1067 [ + - - + : 2 : BOOST_CHECK_THROW(ReadFromStream(addrman2, ssPeers2), std::ios_base::failure);
- - - - -
+ + - +
- ]
1068 : 1 : }
1069 : :
1070 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(addrman_update_address)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
1071 : : {
1072 : : // Tests updating nTime via Connected() and nServices via SetServices() and Add()
1073 : 1 : auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
1074 [ + - + - ]: 1 : CNetAddr source{ResolveIP("252.2.2.2")};
1075 [ + - + - ]: 1 : CAddress addr{CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE)};
1076 : :
1077 : 1 : const auto start_time{Now<NodeSeconds>() - 10000s};
1078 : 1 : addr.nTime = start_time;
1079 [ + - + - : 3 : BOOST_CHECK(addrman->Add({addr}, source));
+ - + - +
+ - - ]
1080 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(), 1U);
+ - ]
1081 : :
1082 : : // Updating an addrman entry with a different port doesn't change it
1083 [ + - + - ]: 1 : CAddress addr_diff_port{CAddress(ResolveService("250.1.1.1", 8334), NODE_NONE)};
1084 : 1 : addr_diff_port.nTime = start_time;
1085 [ + - ]: 1 : addrman->Connected(addr_diff_port);
1086 [ + - ]: 1 : addrman->SetServices(addr_diff_port, NODE_NETWORK_LIMITED);
1087 [ + - ]: 1 : std::vector<CAddress> vAddr1{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};
1088 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(vAddr1.size(), 1U);
1089 [ + - + - : 2 : BOOST_CHECK(vAddr1.at(0).nTime == start_time);
+ - + - ]
1090 [ + - + - : 1 : BOOST_CHECK_EQUAL(vAddr1.at(0).nServices, NODE_NONE);
+ - ]
1091 : :
1092 : : // Updating an addrman entry with the correct port is successful
1093 [ + - ]: 1 : addrman->Connected(addr);
1094 [ + - ]: 1 : addrman->SetServices(addr, NODE_NETWORK_LIMITED);
1095 [ + - ]: 1 : std::vector<CAddress> vAddr2 = addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt);
1096 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(vAddr2.size(), 1U);
1097 [ + - + - : 2 : BOOST_CHECK(vAddr2.at(0).nTime >= start_time + 10000s);
+ - + - ]
1098 [ + - + - : 1 : BOOST_CHECK_EQUAL(vAddr2.at(0).nServices, NODE_NETWORK_LIMITED);
+ - ]
1099 : :
1100 : : // Updating an existing addr through Add() (used in gossip relay) can add additional services but can't remove existing ones.
1101 [ + - + - ]: 1 : CAddress addr_v2{CAddress(ResolveService("250.1.1.1", 8333), NODE_P2P_V2)};
1102 : 1 : addr_v2.nTime = start_time;
1103 [ + - + - : 3 : BOOST_CHECK(!addrman->Add({addr_v2}, source));
+ - + - +
+ - - ]
1104 [ + - ]: 1 : std::vector<CAddress> vAddr3{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};
1105 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(vAddr3.size(), 1U);
1106 [ + - + - : 1 : BOOST_CHECK_EQUAL(vAddr3.at(0).nServices, NODE_P2P_V2 | NODE_NETWORK_LIMITED);
+ - ]
1107 : :
1108 : : // SetServices() (used when we connected to them) overwrites existing service flags
1109 [ + - ]: 1 : addrman->SetServices(addr, NODE_NETWORK);
1110 [ + - ]: 1 : std::vector<CAddress> vAddr4{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};
1111 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(vAddr4.size(), 1U);
1112 [ + - + - : 1 : BOOST_CHECK_EQUAL(vAddr4.at(0).nServices, NODE_NETWORK);
+ - ]
1113 : :
1114 : : // Promoting to Tried does not affect the service flags
1115 [ + - + - : 2 : BOOST_CHECK(addrman->Good(addr)); // addr has NODE_NONE
+ - + - ]
1116 [ + - ]: 1 : std::vector<CAddress> vAddr5{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};
1117 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(vAddr5.size(), 1U);
1118 [ + - + - : 1 : BOOST_CHECK_EQUAL(vAddr5.at(0).nServices, NODE_NETWORK);
+ - ]
1119 : :
1120 : : // Adding service flags even works when the addr is in Tried
1121 [ + - + - : 3 : BOOST_CHECK(!addrman->Add({addr_v2}, source));
+ - + - +
+ - - ]
1122 [ + - ]: 1 : std::vector<CAddress> vAddr6{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};
1123 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(vAddr6.size(), 1U);
1124 [ + - + - : 1 : BOOST_CHECK_EQUAL(vAddr6.at(0).nServices, NODE_NETWORK | NODE_P2P_V2);
+ - ]
1125 : 4 : }
1126 : :
1127 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(addrman_size)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
1128 : : {
1129 : 1 : auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
1130 [ + - + - ]: 1 : const CNetAddr source = ResolveIP("252.2.2.2");
1131 : :
1132 : : // empty addrman
1133 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/std::nullopt), 0U);
+ - ]
1134 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/std::nullopt), 0U);
+ - ]
1135 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/true), 0U);
+ - ]
1136 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/false), 0U);
+ - ]
1137 : :
1138 : : // add two ipv4 addresses, one to tried and new
1139 [ + - + - ]: 1 : const CAddress addr1{ResolveService("250.1.1.1", 8333), NODE_NONE};
1140 [ + - + - : 3 : BOOST_CHECK(addrman->Add({addr1}, source));
+ - + - +
+ - - ]
1141 [ + - + - : 2 : BOOST_CHECK(addrman->Good(addr1));
+ - + - ]
1142 [ + - + - ]: 1 : const CAddress addr2{ResolveService("250.1.1.2", 8333), NODE_NONE};
1143 [ + - + - : 3 : BOOST_CHECK(addrman->Add({addr2}, source));
+ - + - +
+ - - ]
1144 : :
1145 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/std::nullopt), 2U);
+ - ]
1146 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/std::nullopt), 2U);
+ - ]
1147 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/true), 1U);
+ - ]
1148 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/false), 1U);
+ - ]
1149 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/true), 1U);
+ - ]
1150 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/false), 1U);
+ - ]
1151 : :
1152 : : // add one i2p address to new
1153 [ + - ]: 1 : CService i2p_addr;
1154 [ + - + - ]: 1 : i2p_addr.SetSpecial("UDHDrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.I2P");
1155 : 1 : const CAddress addr3{i2p_addr, NODE_NONE};
1156 [ + - + - : 3 : BOOST_CHECK(addrman->Add({addr3}, source));
+ - + - +
+ - - ]
1157 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/std::nullopt), 3U);
+ - ]
1158 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/std::nullopt), 2U);
+ - ]
1159 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_I2P, /*in_new=*/std::nullopt), 1U);
+ - ]
1160 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_I2P, /*in_new=*/true), 1U);
+ - ]
1161 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/true), 2U);
+ - ]
1162 [ + - + - : 1 : BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/false), 1U);
+ - ]
1163 : 4 : }
1164 : :
1165 : : BOOST_AUTO_TEST_SUITE_END()
|