Line data Source code
1 : // Copyright (c) 2012-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 <test/util/setup_common.h>
6 :
7 : #include <chainparams.h>
8 : #include <clientversion.h>
9 : #include <compat/compat.h>
10 : #include <net.h>
11 : #include <net_processing.h>
12 : #include <netaddress.h>
13 : #include <netbase.h>
14 : #include <netmessagemaker.h>
15 : #include <serialize.h>
16 : #include <span.h>
17 : #include <streams.h>
18 : #include <test/util/random.h>
19 : #include <test/util/validation.h>
20 : #include <timedata.h>
21 : #include <util/strencodings.h>
22 : #include <util/string.h>
23 : #include <util/system.h>
24 : #include <validation.h>
25 : #include <version.h>
26 :
27 : #include <boost/test/unit_test.hpp>
28 :
29 : #include <algorithm>
30 : #include <cstdint>
31 : #include <ios>
32 : #include <memory>
33 : #include <optional>
34 : #include <string>
35 :
36 : using namespace std::literals;
37 :
38 146 : BOOST_FIXTURE_TEST_SUITE(net_tests, RegTestingSetup)
39 :
40 149 : BOOST_AUTO_TEST_CASE(cnode_listen_port)
41 : {
42 : // test default
43 1 : uint16_t port{GetListenPort()};
44 1 : BOOST_CHECK(port == Params().GetDefaultPort());
45 : // test set port
46 1 : uint16_t altPort = 12345;
47 1 : BOOST_CHECK(gArgs.SoftSetArg("-port", ToString(altPort)));
48 1 : port = GetListenPort();
49 1 : BOOST_CHECK(port == altPort);
50 1 : }
51 :
52 149 : BOOST_AUTO_TEST_CASE(cnode_simple_test)
53 : {
54 1 : NodeId id = 0;
55 :
56 : in_addr ipv4Addr;
57 1 : ipv4Addr.s_addr = 0xa0b0c001;
58 :
59 1 : CAddress addr = CAddress(CService(ipv4Addr, 7777), NODE_NETWORK);
60 1 : std::string pszDest;
61 :
62 1 : std::unique_ptr<CNode> pnode1 = std::make_unique<CNode>(id++,
63 1 : /*sock=*/nullptr,
64 : addr,
65 1 : /*nKeyedNetGroupIn=*/0,
66 1 : /*nLocalHostNonceIn=*/0,
67 1 : CAddress(),
68 : pszDest,
69 1 : ConnectionType::OUTBOUND_FULL_RELAY,
70 1 : /*inbound_onion=*/false);
71 1 : BOOST_CHECK(pnode1->IsFullOutboundConn() == true);
72 1 : BOOST_CHECK(pnode1->IsManualConn() == false);
73 1 : BOOST_CHECK(pnode1->IsBlockOnlyConn() == false);
74 1 : BOOST_CHECK(pnode1->IsFeelerConn() == false);
75 1 : BOOST_CHECK(pnode1->IsAddrFetchConn() == false);
76 1 : BOOST_CHECK(pnode1->IsInboundConn() == false);
77 1 : BOOST_CHECK(pnode1->m_inbound_onion == false);
78 1 : BOOST_CHECK_EQUAL(pnode1->ConnectedThroughNetwork(), Network::NET_IPV4);
79 :
80 1 : std::unique_ptr<CNode> pnode2 = std::make_unique<CNode>(id++,
81 1 : /*sock=*/nullptr,
82 : addr,
83 1 : /*nKeyedNetGroupIn=*/1,
84 1 : /*nLocalHostNonceIn=*/1,
85 1 : CAddress(),
86 : pszDest,
87 1 : ConnectionType::INBOUND,
88 1 : /*inbound_onion=*/false);
89 1 : BOOST_CHECK(pnode2->IsFullOutboundConn() == false);
90 1 : BOOST_CHECK(pnode2->IsManualConn() == false);
91 1 : BOOST_CHECK(pnode2->IsBlockOnlyConn() == false);
92 1 : BOOST_CHECK(pnode2->IsFeelerConn() == false);
93 1 : BOOST_CHECK(pnode2->IsAddrFetchConn() == false);
94 1 : BOOST_CHECK(pnode2->IsInboundConn() == true);
95 1 : BOOST_CHECK(pnode2->m_inbound_onion == false);
96 1 : BOOST_CHECK_EQUAL(pnode2->ConnectedThroughNetwork(), Network::NET_IPV4);
97 :
98 1 : std::unique_ptr<CNode> pnode3 = std::make_unique<CNode>(id++,
99 1 : /*sock=*/nullptr,
100 : addr,
101 1 : /*nKeyedNetGroupIn=*/0,
102 1 : /*nLocalHostNonceIn=*/0,
103 1 : CAddress(),
104 : pszDest,
105 1 : ConnectionType::OUTBOUND_FULL_RELAY,
106 1 : /*inbound_onion=*/false);
107 1 : BOOST_CHECK(pnode3->IsFullOutboundConn() == true);
108 1 : BOOST_CHECK(pnode3->IsManualConn() == false);
109 1 : BOOST_CHECK(pnode3->IsBlockOnlyConn() == false);
110 1 : BOOST_CHECK(pnode3->IsFeelerConn() == false);
111 1 : BOOST_CHECK(pnode3->IsAddrFetchConn() == false);
112 1 : BOOST_CHECK(pnode3->IsInboundConn() == false);
113 1 : BOOST_CHECK(pnode3->m_inbound_onion == false);
114 1 : BOOST_CHECK_EQUAL(pnode3->ConnectedThroughNetwork(), Network::NET_IPV4);
115 :
116 1 : std::unique_ptr<CNode> pnode4 = std::make_unique<CNode>(id++,
117 1 : /*sock=*/nullptr,
118 : addr,
119 1 : /*nKeyedNetGroupIn=*/1,
120 1 : /*nLocalHostNonceIn=*/1,
121 1 : CAddress(),
122 : pszDest,
123 1 : ConnectionType::INBOUND,
124 1 : /*inbound_onion=*/true);
125 1 : BOOST_CHECK(pnode4->IsFullOutboundConn() == false);
126 1 : BOOST_CHECK(pnode4->IsManualConn() == false);
127 1 : BOOST_CHECK(pnode4->IsBlockOnlyConn() == false);
128 1 : BOOST_CHECK(pnode4->IsFeelerConn() == false);
129 1 : BOOST_CHECK(pnode4->IsAddrFetchConn() == false);
130 1 : BOOST_CHECK(pnode4->IsInboundConn() == true);
131 1 : BOOST_CHECK(pnode4->m_inbound_onion == true);
132 1 : BOOST_CHECK_EQUAL(pnode4->ConnectedThroughNetwork(), Network::NET_ONION);
133 1 : }
134 :
135 149 : BOOST_AUTO_TEST_CASE(cnetaddr_basic)
136 : {
137 1 : CNetAddr addr;
138 :
139 : // IPv4, INADDR_ANY
140 1 : addr = LookupHost("0.0.0.0", false).value();
141 1 : BOOST_REQUIRE(!addr.IsValid());
142 1 : BOOST_REQUIRE(addr.IsIPv4());
143 :
144 1 : BOOST_CHECK(addr.IsBindAny());
145 1 : BOOST_CHECK(addr.IsAddrV1Compatible());
146 1 : BOOST_CHECK_EQUAL(addr.ToStringAddr(), "0.0.0.0");
147 :
148 : // IPv4, INADDR_NONE
149 1 : addr = LookupHost("255.255.255.255", false).value();
150 1 : BOOST_REQUIRE(!addr.IsValid());
151 1 : BOOST_REQUIRE(addr.IsIPv4());
152 :
153 1 : BOOST_CHECK(!addr.IsBindAny());
154 1 : BOOST_CHECK(addr.IsAddrV1Compatible());
155 1 : BOOST_CHECK_EQUAL(addr.ToStringAddr(), "255.255.255.255");
156 :
157 : // IPv4, casual
158 1 : addr = LookupHost("12.34.56.78", false).value();
159 1 : BOOST_REQUIRE(addr.IsValid());
160 1 : BOOST_REQUIRE(addr.IsIPv4());
161 :
162 1 : BOOST_CHECK(!addr.IsBindAny());
163 1 : BOOST_CHECK(addr.IsAddrV1Compatible());
164 1 : BOOST_CHECK_EQUAL(addr.ToStringAddr(), "12.34.56.78");
165 :
166 : // IPv6, in6addr_any
167 1 : addr = LookupHost("::", false).value();
168 1 : BOOST_REQUIRE(!addr.IsValid());
169 1 : BOOST_REQUIRE(addr.IsIPv6());
170 :
171 1 : BOOST_CHECK(addr.IsBindAny());
172 1 : BOOST_CHECK(addr.IsAddrV1Compatible());
173 1 : BOOST_CHECK_EQUAL(addr.ToStringAddr(), "::");
174 :
175 : // IPv6, casual
176 1 : addr = LookupHost("1122:3344:5566:7788:9900:aabb:ccdd:eeff", false).value();
177 1 : BOOST_REQUIRE(addr.IsValid());
178 1 : BOOST_REQUIRE(addr.IsIPv6());
179 :
180 1 : BOOST_CHECK(!addr.IsBindAny());
181 1 : BOOST_CHECK(addr.IsAddrV1Compatible());
182 1 : BOOST_CHECK_EQUAL(addr.ToStringAddr(), "1122:3344:5566:7788:9900:aabb:ccdd:eeff");
183 :
184 : // IPv6, scoped/link-local. See https://tools.ietf.org/html/rfc4007
185 : // We support non-negative decimal integers (uint32_t) as zone id indices.
186 : // Normal link-local scoped address functionality is to append "%" plus the
187 : // zone id, for example, given a link-local address of "fe80::1" and a zone
188 : // id of "32", return the address as "fe80::1%32".
189 1 : const std::string link_local{"fe80::1"};
190 1 : const std::string scoped_addr{link_local + "%32"};
191 1 : addr = LookupHost(scoped_addr, false).value();
192 1 : BOOST_REQUIRE(addr.IsValid());
193 1 : BOOST_REQUIRE(addr.IsIPv6());
194 1 : BOOST_CHECK(!addr.IsBindAny());
195 1 : BOOST_CHECK_EQUAL(addr.ToStringAddr(), scoped_addr);
196 :
197 : // Test that the delimiter "%" and default zone id of 0 can be omitted for the default scope.
198 1 : addr = LookupHost(link_local + "%0", false).value();
199 1 : BOOST_REQUIRE(addr.IsValid());
200 1 : BOOST_REQUIRE(addr.IsIPv6());
201 1 : BOOST_CHECK(!addr.IsBindAny());
202 1 : BOOST_CHECK_EQUAL(addr.ToStringAddr(), link_local);
203 :
204 : // TORv2, no longer supported
205 1 : BOOST_CHECK(!addr.SetSpecial("6hzph5hv6337r6p2.onion"));
206 :
207 : // TORv3
208 1 : const char* torv3_addr = "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion";
209 1 : BOOST_REQUIRE(addr.SetSpecial(torv3_addr));
210 1 : BOOST_REQUIRE(addr.IsValid());
211 1 : BOOST_REQUIRE(addr.IsTor());
212 :
213 1 : BOOST_CHECK(!addr.IsI2P());
214 1 : BOOST_CHECK(!addr.IsBindAny());
215 1 : BOOST_CHECK(!addr.IsAddrV1Compatible());
216 1 : BOOST_CHECK_EQUAL(addr.ToStringAddr(), torv3_addr);
217 :
218 : // TORv3, broken, with wrong checksum
219 1 : BOOST_CHECK(!addr.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscsad.onion"));
220 :
221 : // TORv3, broken, with wrong version
222 1 : BOOST_CHECK(!addr.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscrye.onion"));
223 :
224 : // TORv3, malicious
225 1 : BOOST_CHECK(!addr.SetSpecial(std::string{
226 : "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd\0wtf.onion", 66}));
227 :
228 : // TOR, bogus length
229 1 : BOOST_CHECK(!addr.SetSpecial(std::string{"mfrggzak.onion"}));
230 :
231 : // TOR, invalid base32
232 1 : BOOST_CHECK(!addr.SetSpecial(std::string{"mf*g zak.onion"}));
233 :
234 : // I2P
235 1 : const char* i2p_addr = "UDHDrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.I2P";
236 1 : BOOST_REQUIRE(addr.SetSpecial(i2p_addr));
237 1 : BOOST_REQUIRE(addr.IsValid());
238 1 : BOOST_REQUIRE(addr.IsI2P());
239 :
240 1 : BOOST_CHECK(!addr.IsTor());
241 1 : BOOST_CHECK(!addr.IsBindAny());
242 1 : BOOST_CHECK(!addr.IsAddrV1Compatible());
243 1 : BOOST_CHECK_EQUAL(addr.ToStringAddr(), ToLower(i2p_addr));
244 :
245 : // I2P, correct length, but decodes to less than the expected number of bytes.
246 1 : BOOST_CHECK(!addr.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jn=.b32.i2p"));
247 :
248 : // I2P, extra unnecessary padding
249 1 : BOOST_CHECK(!addr.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna=.b32.i2p"));
250 :
251 : // I2P, malicious
252 1 : BOOST_CHECK(!addr.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v\0wtf.b32.i2p"s));
253 :
254 : // I2P, valid but unsupported (56 Base32 characters)
255 : // See "Encrypted LS with Base 32 Addresses" in
256 : // https://geti2p.net/spec/encryptedleaseset.txt
257 1 : BOOST_CHECK(
258 : !addr.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscsad.b32.i2p"));
259 :
260 : // I2P, invalid base32
261 1 : BOOST_CHECK(!addr.SetSpecial(std::string{"tp*szydbh4dp.b32.i2p"}));
262 :
263 : // Internal
264 1 : addr.SetInternal("esffpp");
265 1 : BOOST_REQUIRE(!addr.IsValid()); // "internal" is considered invalid
266 1 : BOOST_REQUIRE(addr.IsInternal());
267 :
268 1 : BOOST_CHECK(!addr.IsBindAny());
269 1 : BOOST_CHECK(addr.IsAddrV1Compatible());
270 1 : BOOST_CHECK_EQUAL(addr.ToStringAddr(), "esffpvrt3wpeaygy.internal");
271 :
272 : // Totally bogus
273 1 : BOOST_CHECK(!addr.SetSpecial("totally bogus"));
274 1 : }
275 :
276 149 : BOOST_AUTO_TEST_CASE(cnetaddr_tostring_canonical_ipv6)
277 : {
278 : // Test that CNetAddr::ToString formats IPv6 addresses with zero compression as described in
279 : // RFC 5952 ("A Recommendation for IPv6 Address Text Representation").
280 1 : const std::map<std::string, std::string> canonical_representations_ipv6{
281 1 : {"0000:0000:0000:0000:0000:0000:0000:0000", "::"},
282 1 : {"000:0000:000:00:0:00:000:0000", "::"},
283 1 : {"000:000:000:000:000:000:000:000", "::"},
284 1 : {"00:00:00:00:00:00:00:00", "::"},
285 1 : {"0:0:0:0:0:0:0:0", "::"},
286 1 : {"0:0:0:0:0:0:0:1", "::1"},
287 1 : {"2001:0:0:1:0:0:0:1", "2001:0:0:1::1"},
288 1 : {"2001:0db8:0:0:1:0:0:1", "2001:db8::1:0:0:1"},
289 1 : {"2001:0db8:85a3:0000:0000:8a2e:0370:7334", "2001:db8:85a3::8a2e:370:7334"},
290 1 : {"2001:0db8::0001", "2001:db8::1"},
291 1 : {"2001:0db8::0001:0000", "2001:db8::1:0"},
292 1 : {"2001:0db8::1:0:0:1", "2001:db8::1:0:0:1"},
293 1 : {"2001:db8:0000:0:1::1", "2001:db8::1:0:0:1"},
294 1 : {"2001:db8:0000:1:1:1:1:1", "2001:db8:0:1:1:1:1:1"},
295 1 : {"2001:db8:0:0:0:0:2:1", "2001:db8::2:1"},
296 1 : {"2001:db8:0:0:0::1", "2001:db8::1"},
297 1 : {"2001:db8:0:0:1:0:0:1", "2001:db8::1:0:0:1"},
298 1 : {"2001:db8:0:0:1::1", "2001:db8::1:0:0:1"},
299 1 : {"2001:DB8:0:0:1::1", "2001:db8::1:0:0:1"},
300 1 : {"2001:db8:0:0::1", "2001:db8::1"},
301 1 : {"2001:db8:0:0:aaaa::1", "2001:db8::aaaa:0:0:1"},
302 1 : {"2001:db8:0:1:1:1:1:1", "2001:db8:0:1:1:1:1:1"},
303 1 : {"2001:db8:0::1", "2001:db8::1"},
304 1 : {"2001:db8:85a3:0:0:8a2e:370:7334", "2001:db8:85a3::8a2e:370:7334"},
305 1 : {"2001:db8::0:1", "2001:db8::1"},
306 1 : {"2001:db8::0:1:0:0:1", "2001:db8::1:0:0:1"},
307 1 : {"2001:DB8::1", "2001:db8::1"},
308 1 : {"2001:db8::1", "2001:db8::1"},
309 1 : {"2001:db8::1:0:0:1", "2001:db8::1:0:0:1"},
310 1 : {"2001:db8::1:1:1:1:1", "2001:db8:0:1:1:1:1:1"},
311 1 : {"2001:db8::aaaa:0:0:1", "2001:db8::aaaa:0:0:1"},
312 1 : {"2001:db8:aaaa:bbbb:cccc:dddd:0:1", "2001:db8:aaaa:bbbb:cccc:dddd:0:1"},
313 1 : {"2001:db8:aaaa:bbbb:cccc:dddd::1", "2001:db8:aaaa:bbbb:cccc:dddd:0:1"},
314 1 : {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:0001", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:1"},
315 1 : {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:001", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:1"},
316 1 : {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:01", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:1"},
317 1 : {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:1", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:1"},
318 1 : {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa"},
319 1 : {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:AAAA", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa"},
320 1 : {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:AaAa", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa"},
321 : };
322 81 : for (const auto& [input_address, expected_canonical_representation_output] : canonical_representations_ipv6) {
323 40 : const std::optional<CNetAddr> net_addr{LookupHost(input_address, false)};
324 40 : BOOST_REQUIRE(net_addr.value().IsIPv6());
325 40 : BOOST_CHECK_EQUAL(net_addr.value().ToStringAddr(), expected_canonical_representation_output);
326 40 : }
327 1 : }
328 :
329 149 : BOOST_AUTO_TEST_CASE(cnetaddr_serialize_v1)
330 : {
331 1 : CNetAddr addr;
332 1 : CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
333 :
334 1 : s << addr;
335 1 : BOOST_CHECK_EQUAL(HexStr(s), "00000000000000000000000000000000");
336 1 : s.clear();
337 :
338 1 : addr = LookupHost("1.2.3.4", false).value();
339 1 : s << addr;
340 1 : BOOST_CHECK_EQUAL(HexStr(s), "00000000000000000000ffff01020304");
341 1 : s.clear();
342 :
343 1 : addr = LookupHost("1a1b:2a2b:3a3b:4a4b:5a5b:6a6b:7a7b:8a8b", false).value();
344 1 : s << addr;
345 1 : BOOST_CHECK_EQUAL(HexStr(s), "1a1b2a2b3a3b4a4b5a5b6a6b7a7b8a8b");
346 1 : s.clear();
347 :
348 : // TORv2, no longer supported
349 1 : BOOST_CHECK(!addr.SetSpecial("6hzph5hv6337r6p2.onion"));
350 :
351 1 : BOOST_REQUIRE(addr.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion"));
352 1 : s << addr;
353 1 : BOOST_CHECK_EQUAL(HexStr(s), "00000000000000000000000000000000");
354 1 : s.clear();
355 :
356 1 : addr.SetInternal("a");
357 1 : s << addr;
358 1 : BOOST_CHECK_EQUAL(HexStr(s), "fd6b88c08724ca978112ca1bbdcafac2");
359 1 : s.clear();
360 1 : }
361 :
362 149 : BOOST_AUTO_TEST_CASE(cnetaddr_serialize_v2)
363 : {
364 1 : CNetAddr addr;
365 1 : CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
366 : // Add ADDRV2_FORMAT to the version so that the CNetAddr
367 : // serialize method produces an address in v2 format.
368 1 : s.SetVersion(s.GetVersion() | ADDRV2_FORMAT);
369 :
370 1 : s << addr;
371 1 : BOOST_CHECK_EQUAL(HexStr(s), "021000000000000000000000000000000000");
372 1 : s.clear();
373 :
374 1 : addr = LookupHost("1.2.3.4", false).value();
375 1 : s << addr;
376 1 : BOOST_CHECK_EQUAL(HexStr(s), "010401020304");
377 1 : s.clear();
378 :
379 1 : addr = LookupHost("1a1b:2a2b:3a3b:4a4b:5a5b:6a6b:7a7b:8a8b", false).value();
380 1 : s << addr;
381 1 : BOOST_CHECK_EQUAL(HexStr(s), "02101a1b2a2b3a3b4a4b5a5b6a6b7a7b8a8b");
382 1 : s.clear();
383 :
384 : // TORv2, no longer supported
385 1 : BOOST_CHECK(!addr.SetSpecial("6hzph5hv6337r6p2.onion"));
386 :
387 1 : BOOST_REQUIRE(addr.SetSpecial("kpgvmscirrdqpekbqjsvw5teanhatztpp2gl6eee4zkowvwfxwenqaid.onion"));
388 1 : s << addr;
389 1 : BOOST_CHECK_EQUAL(HexStr(s), "042053cd5648488c4707914182655b7664034e09e66f7e8cbf1084e654eb56c5bd88");
390 1 : s.clear();
391 :
392 1 : BOOST_REQUIRE(addr.SetInternal("a"));
393 1 : s << addr;
394 1 : BOOST_CHECK_EQUAL(HexStr(s), "0210fd6b88c08724ca978112ca1bbdcafac2");
395 1 : s.clear();
396 1 : }
397 :
398 149 : BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
399 : {
400 1 : CNetAddr addr;
401 1 : CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
402 : // Add ADDRV2_FORMAT to the version so that the CNetAddr
403 : // unserialize method expects an address in v2 format.
404 1 : s.SetVersion(s.GetVersion() | ADDRV2_FORMAT);
405 :
406 : // Valid IPv4.
407 1 : s << Span{ParseHex("01" // network type (IPv4)
408 : "04" // address length
409 : "01020304")}; // address
410 1 : s >> addr;
411 1 : BOOST_CHECK(addr.IsValid());
412 1 : BOOST_CHECK(addr.IsIPv4());
413 1 : BOOST_CHECK(addr.IsAddrV1Compatible());
414 1 : BOOST_CHECK_EQUAL(addr.ToStringAddr(), "1.2.3.4");
415 1 : BOOST_REQUIRE(s.empty());
416 :
417 : // Invalid IPv4, valid length but address itself is shorter.
418 1 : s << Span{ParseHex("01" // network type (IPv4)
419 : "04" // address length
420 : "0102")}; // address
421 2 : BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure, HasReason("end of data"));
422 1 : BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
423 1 : s.clear();
424 :
425 : // Invalid IPv4, with bogus length.
426 1 : s << Span{ParseHex("01" // network type (IPv4)
427 : "05" // address length
428 : "01020304")}; // address
429 2 : BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
430 : HasReason("BIP155 IPv4 address with length 5 (should be 4)"));
431 1 : BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
432 1 : s.clear();
433 :
434 : // Invalid IPv4, with extreme length.
435 1 : s << Span{ParseHex("01" // network type (IPv4)
436 : "fd0102" // address length (513 as CompactSize)
437 : "01020304")}; // address
438 2 : BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
439 : HasReason("Address too long: 513 > 512"));
440 1 : BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
441 1 : s.clear();
442 :
443 : // Valid IPv6.
444 1 : s << Span{ParseHex("02" // network type (IPv6)
445 : "10" // address length
446 : "0102030405060708090a0b0c0d0e0f10")}; // address
447 1 : s >> addr;
448 1 : BOOST_CHECK(addr.IsValid());
449 1 : BOOST_CHECK(addr.IsIPv6());
450 1 : BOOST_CHECK(addr.IsAddrV1Compatible());
451 1 : BOOST_CHECK_EQUAL(addr.ToStringAddr(), "102:304:506:708:90a:b0c:d0e:f10");
452 1 : BOOST_REQUIRE(s.empty());
453 :
454 : // Valid IPv6, contains embedded "internal".
455 1 : s << Span{ParseHex(
456 1 : "02" // network type (IPv6)
457 : "10" // address length
458 : "fd6b88c08724ca978112ca1bbdcafac2")}; // address: 0xfd + sha256("bitcoin")[0:5] +
459 : // sha256(name)[0:10]
460 1 : s >> addr;
461 1 : BOOST_CHECK(addr.IsInternal());
462 1 : BOOST_CHECK(addr.IsAddrV1Compatible());
463 1 : BOOST_CHECK_EQUAL(addr.ToStringAddr(), "zklycewkdo64v6wc.internal");
464 1 : BOOST_REQUIRE(s.empty());
465 :
466 : // Invalid IPv6, with bogus length.
467 1 : s << Span{ParseHex("02" // network type (IPv6)
468 : "04" // address length
469 : "00")}; // address
470 2 : BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
471 : HasReason("BIP155 IPv6 address with length 4 (should be 16)"));
472 1 : BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
473 1 : s.clear();
474 :
475 : // Invalid IPv6, contains embedded IPv4.
476 1 : s << Span{ParseHex("02" // network type (IPv6)
477 : "10" // address length
478 : "00000000000000000000ffff01020304")}; // address
479 1 : s >> addr;
480 1 : BOOST_CHECK(!addr.IsValid());
481 1 : BOOST_REQUIRE(s.empty());
482 :
483 : // Invalid IPv6, contains embedded TORv2.
484 1 : s << Span{ParseHex("02" // network type (IPv6)
485 : "10" // address length
486 : "fd87d87eeb430102030405060708090a")}; // address
487 1 : s >> addr;
488 1 : BOOST_CHECK(!addr.IsValid());
489 1 : BOOST_REQUIRE(s.empty());
490 :
491 : // TORv2, no longer supported.
492 1 : s << Span{ParseHex("03" // network type (TORv2)
493 : "0a" // address length
494 : "f1f2f3f4f5f6f7f8f9fa")}; // address
495 1 : s >> addr;
496 1 : BOOST_CHECK(!addr.IsValid());
497 1 : BOOST_REQUIRE(s.empty());
498 :
499 : // Valid TORv3.
500 1 : s << Span{ParseHex("04" // network type (TORv3)
501 : "20" // address length
502 : "79bcc625184b05194975c28b66b66b04" // address
503 : "69f7f6556fb1ac3189a79b40dda32f1f"
504 : )};
505 1 : s >> addr;
506 1 : BOOST_CHECK(addr.IsValid());
507 1 : BOOST_CHECK(addr.IsTor());
508 1 : BOOST_CHECK(!addr.IsAddrV1Compatible());
509 1 : BOOST_CHECK_EQUAL(addr.ToStringAddr(),
510 : "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion");
511 1 : BOOST_REQUIRE(s.empty());
512 :
513 : // Invalid TORv3, with bogus length.
514 1 : s << Span{ParseHex("04" // network type (TORv3)
515 : "00" // address length
516 : "00" // address
517 : )};
518 2 : BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
519 : HasReason("BIP155 TORv3 address with length 0 (should be 32)"));
520 1 : BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
521 1 : s.clear();
522 :
523 : // Valid I2P.
524 1 : s << Span{ParseHex("05" // network type (I2P)
525 : "20" // address length
526 : "a2894dabaec08c0051a481a6dac88b64" // address
527 : "f98232ae42d4b6fd2fa81952dfe36a87")};
528 1 : s >> addr;
529 1 : BOOST_CHECK(addr.IsValid());
530 1 : BOOST_CHECK(addr.IsI2P());
531 1 : BOOST_CHECK(!addr.IsAddrV1Compatible());
532 1 : BOOST_CHECK_EQUAL(addr.ToStringAddr(),
533 : "ukeu3k5oycgaauneqgtnvselmt4yemvoilkln7jpvamvfx7dnkdq.b32.i2p");
534 1 : BOOST_REQUIRE(s.empty());
535 :
536 : // Invalid I2P, with bogus length.
537 1 : s << Span{ParseHex("05" // network type (I2P)
538 : "03" // address length
539 : "00" // address
540 : )};
541 2 : BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
542 : HasReason("BIP155 I2P address with length 3 (should be 32)"));
543 1 : BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
544 1 : s.clear();
545 :
546 : // Valid CJDNS.
547 1 : s << Span{ParseHex("06" // network type (CJDNS)
548 : "10" // address length
549 : "fc000001000200030004000500060007" // address
550 : )};
551 1 : s >> addr;
552 1 : BOOST_CHECK(addr.IsValid());
553 1 : BOOST_CHECK(addr.IsCJDNS());
554 1 : BOOST_CHECK(!addr.IsAddrV1Compatible());
555 1 : BOOST_CHECK_EQUAL(addr.ToStringAddr(), "fc00:1:2:3:4:5:6:7");
556 1 : BOOST_REQUIRE(s.empty());
557 :
558 : // Invalid CJDNS, wrong prefix.
559 1 : s << Span{ParseHex("06" // network type (CJDNS)
560 : "10" // address length
561 : "aa000001000200030004000500060007" // address
562 : )};
563 1 : s >> addr;
564 1 : BOOST_CHECK(addr.IsCJDNS());
565 1 : BOOST_CHECK(!addr.IsValid());
566 1 : BOOST_REQUIRE(s.empty());
567 :
568 : // Invalid CJDNS, with bogus length.
569 1 : s << Span{ParseHex("06" // network type (CJDNS)
570 : "01" // address length
571 : "00" // address
572 : )};
573 2 : BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
574 : HasReason("BIP155 CJDNS address with length 1 (should be 16)"));
575 1 : BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
576 1 : s.clear();
577 :
578 : // Unknown, with extreme length.
579 1 : s << Span{ParseHex("aa" // network type (unknown)
580 : "fe00000002" // address length (CompactSize's MAX_SIZE)
581 : "01020304050607" // address
582 : )};
583 2 : BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
584 : HasReason("Address too long: 33554432 > 512"));
585 1 : BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
586 1 : s.clear();
587 :
588 : // Unknown, with reasonable length.
589 1 : s << Span{ParseHex("aa" // network type (unknown)
590 : "04" // address length
591 : "01020304" // address
592 : )};
593 1 : s >> addr;
594 1 : BOOST_CHECK(!addr.IsValid());
595 1 : BOOST_REQUIRE(s.empty());
596 :
597 : // Unknown, with zero length.
598 1 : s << Span{ParseHex("aa" // network type (unknown)
599 : "00" // address length
600 : "" // address
601 : )};
602 1 : s >> addr;
603 1 : BOOST_CHECK(!addr.IsValid());
604 1 : BOOST_REQUIRE(s.empty());
605 9 : }
606 :
607 : // prior to PR #14728, this test triggers an undefined behavior
608 149 : BOOST_AUTO_TEST_CASE(ipv4_peer_with_ipv6_addrMe_test)
609 : {
610 : // set up local addresses; all that's necessary to reproduce the bug is
611 : // that a normal IPv4 address is among the entries, but if this address is
612 : // !IsRoutable the undefined behavior is easier to trigger deterministically
613 : in_addr raw_addr;
614 1 : raw_addr.s_addr = htonl(0x7f000001);
615 1 : const CNetAddr mapLocalHost_entry = CNetAddr(raw_addr);
616 : {
617 1 : LOCK(g_maplocalhost_mutex);
618 : LocalServiceInfo lsi;
619 1 : lsi.nScore = 23;
620 1 : lsi.nPort = 42;
621 1 : mapLocalHost[mapLocalHost_entry] = lsi;
622 1 : }
623 :
624 : // create a peer with an IPv4 address
625 : in_addr ipv4AddrPeer;
626 1 : ipv4AddrPeer.s_addr = 0xa0b0c001;
627 1 : CAddress addr = CAddress(CService(ipv4AddrPeer, 7777), NODE_NETWORK);
628 1 : std::unique_ptr<CNode> pnode = std::make_unique<CNode>(/*id=*/0,
629 1 : /*sock=*/nullptr,
630 : addr,
631 1 : /*nKeyedNetGroupIn=*/0,
632 1 : /*nLocalHostNonceIn=*/0,
633 1 : CAddress{},
634 1 : /*pszDest=*/std::string{},
635 1 : ConnectionType::OUTBOUND_FULL_RELAY,
636 1 : /*inbound_onion=*/false);
637 1 : pnode->fSuccessfullyConnected.store(true);
638 :
639 : // the peer claims to be reaching us via IPv6
640 : in6_addr ipv6AddrLocal;
641 1 : memset(ipv6AddrLocal.s6_addr, 0, 16);
642 1 : ipv6AddrLocal.s6_addr[0] = 0xcc;
643 1 : CAddress addrLocal = CAddress(CService(ipv6AddrLocal, 7777), NODE_NETWORK);
644 1 : pnode->SetAddrLocal(addrLocal);
645 :
646 : // before patch, this causes undefined behavior detectable with clang's -fsanitize=memory
647 1 : GetLocalAddrForPeer(*pnode);
648 :
649 : // suppress no-checks-run warning; if this test fails, it's by triggering a sanitizer
650 1 : BOOST_CHECK(1);
651 :
652 : // Cleanup, so that we don't confuse other tests.
653 : {
654 1 : LOCK(g_maplocalhost_mutex);
655 1 : mapLocalHost.erase(mapLocalHost_entry);
656 1 : }
657 1 : }
658 :
659 149 : BOOST_AUTO_TEST_CASE(get_local_addr_for_peer_port)
660 : {
661 : // Test that GetLocalAddrForPeer() properly selects the address to self-advertise:
662 : //
663 : // 1. GetLocalAddrForPeer() calls GetLocalAddress() which returns an address that is
664 : // not routable.
665 : // 2. GetLocalAddrForPeer() overrides the address with whatever the peer has told us
666 : // he sees us as.
667 : // 2.1. For inbound connections we must override both the address and the port.
668 : // 2.2. For outbound connections we must override only the address.
669 :
670 : // Pretend that we bound to this port.
671 1 : const uint16_t bind_port = 20001;
672 1 : m_node.args->ForceSetArg("-bind", strprintf("3.4.5.6:%u", bind_port));
673 :
674 : // Our address:port as seen from the peer, completely different from the above.
675 : in_addr peer_us_addr;
676 1 : peer_us_addr.s_addr = htonl(0x02030405);
677 1 : const CService peer_us{peer_us_addr, 20002};
678 :
679 : // Create a peer with a routable IPv4 address (outbound).
680 : in_addr peer_out_in_addr;
681 1 : peer_out_in_addr.s_addr = htonl(0x01020304);
682 1 : CNode peer_out{/*id=*/0,
683 1 : /*sock=*/nullptr,
684 1 : /*addrIn=*/CAddress{CService{peer_out_in_addr, 8333}, NODE_NETWORK},
685 : /*nKeyedNetGroupIn=*/0,
686 : /*nLocalHostNonceIn=*/0,
687 1 : /*addrBindIn=*/CAddress{},
688 1 : /*addrNameIn=*/std::string{},
689 : /*conn_type_in=*/ConnectionType::OUTBOUND_FULL_RELAY,
690 : /*inbound_onion=*/false};
691 1 : peer_out.fSuccessfullyConnected = true;
692 1 : peer_out.SetAddrLocal(peer_us);
693 :
694 : // Without the fix peer_us:8333 is chosen instead of the proper peer_us:bind_port.
695 1 : auto chosen_local_addr = GetLocalAddrForPeer(peer_out);
696 1 : BOOST_REQUIRE(chosen_local_addr);
697 1 : const CService expected{peer_us_addr, bind_port};
698 1 : BOOST_CHECK(*chosen_local_addr == expected);
699 :
700 : // Create a peer with a routable IPv4 address (inbound).
701 : in_addr peer_in_in_addr;
702 1 : peer_in_in_addr.s_addr = htonl(0x05060708);
703 1 : CNode peer_in{/*id=*/0,
704 1 : /*sock=*/nullptr,
705 1 : /*addrIn=*/CAddress{CService{peer_in_in_addr, 8333}, NODE_NETWORK},
706 : /*nKeyedNetGroupIn=*/0,
707 : /*nLocalHostNonceIn=*/0,
708 1 : /*addrBindIn=*/CAddress{},
709 1 : /*addrNameIn=*/std::string{},
710 : /*conn_type_in=*/ConnectionType::INBOUND,
711 : /*inbound_onion=*/false};
712 1 : peer_in.fSuccessfullyConnected = true;
713 1 : peer_in.SetAddrLocal(peer_us);
714 :
715 : // Without the fix peer_us:8333 is chosen instead of the proper peer_us:peer_us.GetPort().
716 1 : chosen_local_addr = GetLocalAddrForPeer(peer_in);
717 1 : BOOST_REQUIRE(chosen_local_addr);
718 1 : BOOST_CHECK(*chosen_local_addr == peer_us);
719 :
720 1 : m_node.args->ForceSetArg("-bind", "");
721 1 : }
722 :
723 149 : BOOST_AUTO_TEST_CASE(LimitedAndReachable_Network)
724 : {
725 1 : BOOST_CHECK(g_reachable_nets.Contains(NET_IPV4));
726 1 : BOOST_CHECK(g_reachable_nets.Contains(NET_IPV6));
727 1 : BOOST_CHECK(g_reachable_nets.Contains(NET_ONION));
728 1 : BOOST_CHECK(g_reachable_nets.Contains(NET_I2P));
729 1 : BOOST_CHECK(g_reachable_nets.Contains(NET_CJDNS));
730 :
731 1 : g_reachable_nets.Remove(NET_IPV4);
732 1 : g_reachable_nets.Remove(NET_IPV6);
733 1 : g_reachable_nets.Remove(NET_ONION);
734 1 : g_reachable_nets.Remove(NET_I2P);
735 1 : g_reachable_nets.Remove(NET_CJDNS);
736 :
737 1 : BOOST_CHECK(!g_reachable_nets.Contains(NET_IPV4));
738 1 : BOOST_CHECK(!g_reachable_nets.Contains(NET_IPV6));
739 1 : BOOST_CHECK(!g_reachable_nets.Contains(NET_ONION));
740 1 : BOOST_CHECK(!g_reachable_nets.Contains(NET_I2P));
741 1 : BOOST_CHECK(!g_reachable_nets.Contains(NET_CJDNS));
742 :
743 1 : g_reachable_nets.Add(NET_IPV4);
744 1 : g_reachable_nets.Add(NET_IPV6);
745 1 : g_reachable_nets.Add(NET_ONION);
746 1 : g_reachable_nets.Add(NET_I2P);
747 1 : g_reachable_nets.Add(NET_CJDNS);
748 :
749 1 : BOOST_CHECK(g_reachable_nets.Contains(NET_IPV4));
750 1 : BOOST_CHECK(g_reachable_nets.Contains(NET_IPV6));
751 1 : BOOST_CHECK(g_reachable_nets.Contains(NET_ONION));
752 1 : BOOST_CHECK(g_reachable_nets.Contains(NET_I2P));
753 1 : BOOST_CHECK(g_reachable_nets.Contains(NET_CJDNS));
754 1 : }
755 :
756 149 : BOOST_AUTO_TEST_CASE(LimitedAndReachable_NetworkCaseUnroutableAndInternal)
757 : {
758 : // Should be reachable by default.
759 1 : BOOST_CHECK(g_reachable_nets.Contains(NET_UNROUTABLE));
760 1 : BOOST_CHECK(g_reachable_nets.Contains(NET_INTERNAL));
761 :
762 1 : g_reachable_nets.RemoveAll();
763 :
764 1 : BOOST_CHECK(!g_reachable_nets.Contains(NET_UNROUTABLE));
765 1 : BOOST_CHECK(!g_reachable_nets.Contains(NET_INTERNAL));
766 :
767 1 : g_reachable_nets.Add(NET_IPV4);
768 1 : g_reachable_nets.Add(NET_IPV6);
769 1 : g_reachable_nets.Add(NET_ONION);
770 1 : g_reachable_nets.Add(NET_I2P);
771 1 : g_reachable_nets.Add(NET_CJDNS);
772 1 : g_reachable_nets.Add(NET_UNROUTABLE);
773 1 : g_reachable_nets.Add(NET_INTERNAL);
774 1 : }
775 :
776 2 : CNetAddr UtilBuildAddress(unsigned char p1, unsigned char p2, unsigned char p3, unsigned char p4)
777 : {
778 2 : unsigned char ip[] = {p1, p2, p3, p4};
779 :
780 : struct sockaddr_in sa;
781 2 : memset(&sa, 0, sizeof(sockaddr_in)); // initialize the memory block
782 2 : memcpy(&(sa.sin_addr), &ip, sizeof(ip));
783 2 : return CNetAddr(sa.sin_addr);
784 : }
785 :
786 :
787 149 : BOOST_AUTO_TEST_CASE(LimitedAndReachable_CNetAddr)
788 : {
789 1 : CNetAddr addr = UtilBuildAddress(0x001, 0x001, 0x001, 0x001); // 1.1.1.1
790 :
791 1 : g_reachable_nets.Add(NET_IPV4);
792 1 : BOOST_CHECK(g_reachable_nets.Contains(addr));
793 :
794 1 : g_reachable_nets.Remove(NET_IPV4);
795 1 : BOOST_CHECK(!g_reachable_nets.Contains(addr));
796 :
797 1 : g_reachable_nets.Add(NET_IPV4); // have to reset this, because this is stateful.
798 1 : }
799 :
800 :
801 149 : BOOST_AUTO_TEST_CASE(LocalAddress_BasicLifecycle)
802 : {
803 1 : CService addr = CService(UtilBuildAddress(0x002, 0x001, 0x001, 0x001), 1000); // 2.1.1.1:1000
804 :
805 1 : g_reachable_nets.Add(NET_IPV4);
806 :
807 1 : BOOST_CHECK(!IsLocal(addr));
808 1 : BOOST_CHECK(AddLocal(addr, 1000));
809 1 : BOOST_CHECK(IsLocal(addr));
810 :
811 1 : RemoveLocal(addr);
812 1 : BOOST_CHECK(!IsLocal(addr));
813 1 : }
814 :
815 149 : BOOST_AUTO_TEST_CASE(initial_advertise_from_version_message)
816 : {
817 1 : LOCK(NetEventsInterface::g_msgproc_mutex);
818 :
819 : // Tests the following scenario:
820 : // * -bind=3.4.5.6:20001 is specified
821 : // * we make an outbound connection to a peer
822 : // * the peer reports he sees us as 2.3.4.5:20002 in the version message
823 : // (20002 is a random port assigned by our OS for the outgoing TCP connection,
824 : // we cannot accept connections to it)
825 : // * we should self-advertise to that peer as 2.3.4.5:20001
826 :
827 : // Pretend that we bound to this port.
828 1 : const uint16_t bind_port = 20001;
829 1 : m_node.args->ForceSetArg("-bind", strprintf("3.4.5.6:%u", bind_port));
830 1 : m_node.args->ForceSetArg("-capturemessages", "1");
831 :
832 : // Our address:port as seen from the peer - 2.3.4.5:20002 (different from the above).
833 : in_addr peer_us_addr;
834 1 : peer_us_addr.s_addr = htonl(0x02030405);
835 1 : const CService peer_us{peer_us_addr, 20002};
836 :
837 : // Create a peer with a routable IPv4 address.
838 : in_addr peer_in_addr;
839 1 : peer_in_addr.s_addr = htonl(0x01020304);
840 1 : CNode peer{/*id=*/0,
841 1 : /*sock=*/nullptr,
842 1 : /*addrIn=*/CAddress{CService{peer_in_addr, 8333}, NODE_NETWORK},
843 : /*nKeyedNetGroupIn=*/0,
844 : /*nLocalHostNonceIn=*/0,
845 1 : /*addrBindIn=*/CAddress{},
846 1 : /*addrNameIn=*/std::string{},
847 : /*conn_type_in=*/ConnectionType::OUTBOUND_FULL_RELAY,
848 : /*inbound_onion=*/false};
849 :
850 1 : const uint64_t services{NODE_NETWORK};
851 1 : const int64_t time{0};
852 1 : const CNetMsgMaker msg_maker{PROTOCOL_VERSION};
853 :
854 : // Force CChainState::IsInitialBlockDownload() to return false.
855 : // Otherwise PushAddress() isn't called by PeerManager::ProcessMessage().
856 1 : TestChainState& chainstate =
857 1 : *static_cast<TestChainState*>(&m_node.chainman->ActiveChainstate());
858 1 : chainstate.JumpOutOfIbd();
859 :
860 1 : m_node.peerman->InitializeNode(peer, NODE_NETWORK);
861 :
862 1 : std::atomic<bool> interrupt_dummy{false};
863 1 : std::chrono::microseconds time_received_dummy{0};
864 :
865 : const auto msg_version =
866 1 : msg_maker.Make(NetMsgType::VERSION, PROTOCOL_VERSION, services, time, services, peer_us);
867 1 : CDataStream msg_version_stream{msg_version.data, SER_NETWORK, PROTOCOL_VERSION};
868 :
869 1 : m_node.peerman->ProcessMessage(
870 1 : peer, NetMsgType::VERSION, msg_version_stream, time_received_dummy, interrupt_dummy);
871 :
872 1 : const auto msg_verack = msg_maker.Make(NetMsgType::VERACK);
873 1 : CDataStream msg_verack_stream{msg_verack.data, SER_NETWORK, PROTOCOL_VERSION};
874 :
875 : // Will set peer.fSuccessfullyConnected to true (necessary in SendMessages()).
876 1 : m_node.peerman->ProcessMessage(
877 1 : peer, NetMsgType::VERACK, msg_verack_stream, time_received_dummy, interrupt_dummy);
878 :
879 : // Ensure that peer_us_addr:bind_port is sent to the peer.
880 1 : const CService expected{peer_us_addr, bind_port};
881 1 : bool sent{false};
882 :
883 1 : const auto CaptureMessageOrig = CaptureMessage;
884 4 : CaptureMessage = [&sent, &expected](const CAddress& addr,
885 : const std::string& msg_type,
886 : Span<const unsigned char> data,
887 : bool is_incoming) -> void {
888 3 : if (!is_incoming && msg_type == "addr") {
889 1 : CDataStream s(data, SER_NETWORK, PROTOCOL_VERSION);
890 1 : std::vector<CAddress> addresses;
891 :
892 1 : s >> addresses;
893 :
894 1 : for (const auto& addr : addresses) {
895 1 : if (addr == expected) {
896 1 : sent = true;
897 1 : return;
898 : }
899 : }
900 1 : }
901 3 : };
902 :
903 1 : m_node.peerman->SendMessages(&peer);
904 :
905 1 : BOOST_CHECK(sent);
906 :
907 1 : CaptureMessage = CaptureMessageOrig;
908 1 : chainstate.ResetIbd();
909 1 : m_node.args->ForceSetArg("-capturemessages", "0");
910 1 : m_node.args->ForceSetArg("-bind", "");
911 : // PeerManager::ProcessMessage() calls AddTimeData() which changes the internal state
912 : // in timedata.cpp and later confuses the test "timedata_tests/addtimedata". Thus reset
913 : // that state as it was before our test was run.
914 1 : TestOnlyResetTimeData();
915 1 : }
916 :
917 :
918 149 : BOOST_AUTO_TEST_CASE(advertise_local_address)
919 : {
920 8 : auto CreatePeer = [](const CAddress& addr) {
921 14 : return std::make_unique<CNode>(/*id=*/0,
922 7 : /*sock=*/nullptr,
923 7 : addr,
924 7 : /*nKeyedNetGroupIn=*/0,
925 7 : /*nLocalHostNonceIn=*/0,
926 7 : CAddress{},
927 7 : /*pszDest=*/std::string{},
928 7 : ConnectionType::OUTBOUND_FULL_RELAY,
929 7 : /*inbound_onion=*/false);
930 0 : };
931 1 : g_reachable_nets.Add(NET_CJDNS);
932 :
933 1 : CAddress addr_ipv4{Lookup("1.2.3.4", 8333, false).value(), NODE_NONE};
934 1 : BOOST_REQUIRE(addr_ipv4.IsValid());
935 1 : BOOST_REQUIRE(addr_ipv4.IsIPv4());
936 :
937 1 : CAddress addr_ipv6{Lookup("1122:3344:5566:7788:9900:aabb:ccdd:eeff", 8333, false).value(), NODE_NONE};
938 1 : BOOST_REQUIRE(addr_ipv6.IsValid());
939 1 : BOOST_REQUIRE(addr_ipv6.IsIPv6());
940 :
941 1 : CAddress addr_ipv6_tunnel{Lookup("2002:3344:5566:7788:9900:aabb:ccdd:eeff", 8333, false).value(), NODE_NONE};
942 1 : BOOST_REQUIRE(addr_ipv6_tunnel.IsValid());
943 1 : BOOST_REQUIRE(addr_ipv6_tunnel.IsIPv6());
944 1 : BOOST_REQUIRE(addr_ipv6_tunnel.IsRFC3964());
945 :
946 1 : CAddress addr_teredo{Lookup("2001:0000:5566:7788:9900:aabb:ccdd:eeff", 8333, false).value(), NODE_NONE};
947 1 : BOOST_REQUIRE(addr_teredo.IsValid());
948 1 : BOOST_REQUIRE(addr_teredo.IsIPv6());
949 1 : BOOST_REQUIRE(addr_teredo.IsRFC4380());
950 :
951 1 : CAddress addr_onion;
952 1 : BOOST_REQUIRE(addr_onion.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion"));
953 1 : BOOST_REQUIRE(addr_onion.IsValid());
954 1 : BOOST_REQUIRE(addr_onion.IsTor());
955 :
956 1 : CAddress addr_i2p;
957 1 : BOOST_REQUIRE(addr_i2p.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p"));
958 1 : BOOST_REQUIRE(addr_i2p.IsValid());
959 1 : BOOST_REQUIRE(addr_i2p.IsI2P());
960 :
961 1 : CService service_cjdns{Lookup("fc00:3344:5566:7788:9900:aabb:ccdd:eeff", 8333, false).value(), NODE_NONE};
962 1 : CAddress addr_cjdns{MaybeFlipIPv6toCJDNS(service_cjdns), NODE_NONE};
963 1 : BOOST_REQUIRE(addr_cjdns.IsValid());
964 1 : BOOST_REQUIRE(addr_cjdns.IsCJDNS());
965 :
966 1 : const auto peer_ipv4{CreatePeer(addr_ipv4)};
967 1 : const auto peer_ipv6{CreatePeer(addr_ipv6)};
968 1 : const auto peer_ipv6_tunnel{CreatePeer(addr_ipv6_tunnel)};
969 1 : const auto peer_teredo{CreatePeer(addr_teredo)};
970 1 : const auto peer_onion{CreatePeer(addr_onion)};
971 1 : const auto peer_i2p{CreatePeer(addr_i2p)};
972 1 : const auto peer_cjdns{CreatePeer(addr_cjdns)};
973 :
974 : // one local clearnet address - advertise to all but privacy peers
975 1 : AddLocal(addr_ipv4);
976 1 : BOOST_CHECK(GetLocalAddress(*peer_ipv4) == addr_ipv4);
977 1 : BOOST_CHECK(GetLocalAddress(*peer_ipv6) == addr_ipv4);
978 1 : BOOST_CHECK(GetLocalAddress(*peer_ipv6_tunnel) == addr_ipv4);
979 1 : BOOST_CHECK(GetLocalAddress(*peer_teredo) == addr_ipv4);
980 1 : BOOST_CHECK(GetLocalAddress(*peer_cjdns) == addr_ipv4);
981 1 : BOOST_CHECK(!GetLocalAddress(*peer_onion).IsValid());
982 1 : BOOST_CHECK(!GetLocalAddress(*peer_i2p).IsValid());
983 1 : RemoveLocal(addr_ipv4);
984 :
985 : // local privacy addresses - don't advertise to clearnet peers
986 1 : AddLocal(addr_onion);
987 1 : AddLocal(addr_i2p);
988 1 : BOOST_CHECK(!GetLocalAddress(*peer_ipv4).IsValid());
989 1 : BOOST_CHECK(!GetLocalAddress(*peer_ipv6).IsValid());
990 1 : BOOST_CHECK(!GetLocalAddress(*peer_ipv6_tunnel).IsValid());
991 1 : BOOST_CHECK(!GetLocalAddress(*peer_teredo).IsValid());
992 1 : BOOST_CHECK(!GetLocalAddress(*peer_cjdns).IsValid());
993 1 : BOOST_CHECK(GetLocalAddress(*peer_onion) == addr_onion);
994 1 : BOOST_CHECK(GetLocalAddress(*peer_i2p) == addr_i2p);
995 1 : RemoveLocal(addr_onion);
996 1 : RemoveLocal(addr_i2p);
997 :
998 : // local addresses from all networks
999 1 : AddLocal(addr_ipv4);
1000 1 : AddLocal(addr_ipv6);
1001 1 : AddLocal(addr_ipv6_tunnel);
1002 1 : AddLocal(addr_teredo);
1003 1 : AddLocal(addr_onion);
1004 1 : AddLocal(addr_i2p);
1005 1 : AddLocal(addr_cjdns);
1006 1 : BOOST_CHECK(GetLocalAddress(*peer_ipv4) == addr_ipv4);
1007 1 : BOOST_CHECK(GetLocalAddress(*peer_ipv6) == addr_ipv6);
1008 1 : BOOST_CHECK(GetLocalAddress(*peer_ipv6_tunnel) == addr_ipv6);
1009 1 : BOOST_CHECK(GetLocalAddress(*peer_teredo) == addr_ipv4);
1010 1 : BOOST_CHECK(GetLocalAddress(*peer_onion) == addr_onion);
1011 1 : BOOST_CHECK(GetLocalAddress(*peer_i2p) == addr_i2p);
1012 1 : BOOST_CHECK(GetLocalAddress(*peer_cjdns) == addr_cjdns);
1013 1 : RemoveLocal(addr_ipv4);
1014 1 : RemoveLocal(addr_ipv6);
1015 1 : RemoveLocal(addr_ipv6_tunnel);
1016 1 : RemoveLocal(addr_teredo);
1017 1 : RemoveLocal(addr_onion);
1018 1 : RemoveLocal(addr_i2p);
1019 1 : RemoveLocal(addr_cjdns);
1020 1 : }
1021 :
1022 : namespace {
1023 :
1024 78 : CKey GenerateRandomTestKey() noexcept
1025 : {
1026 78 : CKey key;
1027 78 : uint256 key_data = InsecureRand256();
1028 78 : key.Set(key_data.begin(), key_data.end(), true);
1029 78 : return key;
1030 78 : }
1031 :
1032 : /** A class for scenario-based tests of V2Transport
1033 : *
1034 : * Each V2TransportTester encapsulates a V2Transport (the one being tested), and can be told to
1035 : * interact with it. To do so, it also encapsulates a BIP324Cipher to act as the other side. A
1036 : * second V2Transport is not used, as doing so would not permit scenarios that involve sending
1037 : * invalid data, or ones using BIP324 features that are not implemented on the sending
1038 : * side (like decoy packets).
1039 : */
1040 : class V2TransportTester
1041 : {
1042 : V2Transport m_transport; //!< V2Transport being tested
1043 : BIP324Cipher m_cipher; //!< Cipher to help with the other side
1044 : bool m_test_initiator; //!< Whether m_transport is the initiator (true) or responder (false)
1045 :
1046 : std::vector<uint8_t> m_sent_garbage; //!< The garbage we've sent to m_transport.
1047 : std::vector<uint8_t> m_recv_garbage; //!< The garbage we've received from m_transport.
1048 : std::vector<uint8_t> m_to_send; //!< Bytes we have queued up to send to m_transport.
1049 : std::vector<uint8_t> m_received; //!< Bytes we have received from m_transport.
1050 : std::deque<CSerializedNetMsg> m_msg_to_send; //!< Messages to be sent *by* m_transport to us.
1051 78 : bool m_sent_aad{false};
1052 :
1053 : public:
1054 : /** Construct a tester object. test_initiator: whether the tested transport is initiator. */
1055 156 : V2TransportTester(bool test_initiator) :
1056 78 : m_transport(0, test_initiator, SER_NETWORK, INIT_PROTO_VERSION),
1057 78 : m_cipher{GenerateRandomTestKey(), MakeByteSpan(InsecureRand256())},
1058 78 : m_test_initiator(test_initiator)
1059 78 : {
1060 : // Set peer version for v2 short ID negotiation
1061 78 : m_transport.SetPeerVersion(PROTOCOL_VERSION);
1062 156 : }
1063 :
1064 : /** Data type returned by Interact:
1065 : *
1066 : * - std::nullopt: transport error occurred
1067 : * - otherwise: a vector of
1068 : * - std::nullopt: invalid message received
1069 : * - otherwise: a CNetMessage retrieved
1070 : */
1071 : using InteractResult = std::optional<std::vector<std::optional<CNetMessage>>>;
1072 :
1073 : /** Send/receive scheduled/available bytes and messages.
1074 : *
1075 : * This is the only function that interacts with the transport being tested; everything else is
1076 : * scheduling things done by Interact(), or processing things learned by it.
1077 : */
1078 248 : InteractResult Interact()
1079 : {
1080 248 : std::vector<std::optional<CNetMessage>> ret;
1081 2964 : while (true) {
1082 2964 : bool progress{false};
1083 : // Send bytes from m_to_send to the transport.
1084 2964 : if (!m_to_send.empty()) {
1085 2168 : Span<const uint8_t> to_send = Span{m_to_send}.first(1 + InsecureRandRange(m_to_send.size()));
1086 2168 : size_t old_len = to_send.size();
1087 2168 : if (!m_transport.ReceivedBytes(to_send)) {
1088 23 : return std::nullopt; // transport error occurred
1089 : }
1090 2145 : if (old_len != to_send.size()) {
1091 2054 : progress = true;
1092 2054 : m_to_send.erase(m_to_send.begin(), m_to_send.begin() + (old_len - to_send.size()));
1093 2054 : }
1094 2145 : }
1095 : // Retrieve messages received by the transport.
1096 2941 : if (m_transport.ReceivedMessageComplete() && (!progress || InsecureRandBool())) {
1097 252 : bool reject{false};
1098 252 : auto msg = m_transport.GetReceivedMessage({}, reject);
1099 252 : if (reject) {
1100 61 : ret.emplace_back(std::nullopt);
1101 61 : } else {
1102 191 : ret.emplace_back(std::move(msg));
1103 : }
1104 252 : progress = true;
1105 252 : }
1106 : // Enqueue a message to be sent by the transport to us.
1107 2941 : if (!m_msg_to_send.empty() && (!progress || InsecureRandBool())) {
1108 54 : if (m_transport.SetMessageToSend(m_msg_to_send.front())) {
1109 54 : m_msg_to_send.pop_front();
1110 54 : progress = true;
1111 54 : }
1112 54 : }
1113 : // Receive bytes from the transport.
1114 3959 : const auto& [recv_bytes, _more, _msg_type] = m_transport.GetBytesToSend(!m_msg_to_send.empty());
1115 2941 : if (!recv_bytes.empty() && (!progress || InsecureRandBool())) {
1116 1018 : size_t to_receive = 1 + InsecureRandRange(recv_bytes.size());
1117 3054 : m_received.insert(m_received.end(), recv_bytes.begin(), recv_bytes.begin() + to_receive);
1118 1018 : progress = true;
1119 1018 : m_transport.MarkBytesSent(to_receive);
1120 1018 : }
1121 2941 : if (!progress) break;
1122 : }
1123 225 : return ret;
1124 248 : }
1125 :
1126 : /** Expose the cipher. */
1127 1 : BIP324Cipher& GetCipher() { return m_cipher; }
1128 :
1129 : /** Expose the transport. */
1130 2 : V2Transport& GetTransport() { return m_transport; }
1131 :
1132 : /** Schedule bytes to be sent to the transport. */
1133 49362 : void Send(Span<const uint8_t> data)
1134 : {
1135 49362 : m_to_send.insert(m_to_send.end(), data.begin(), data.end());
1136 49362 : }
1137 :
1138 : /** Send V1 version message header to the transport. */
1139 2 : void SendV1Version(const CMessageHeader::MessageStartChars& magic)
1140 : {
1141 2 : CMessageHeader hdr(magic, "version", 126 + InsecureRandRange(11));
1142 2 : CDataStream ser(SER_NETWORK, CLIENT_VERSION);
1143 2 : ser << hdr;
1144 2 : m_to_send.insert(m_to_send.end(), UCharCast(ser.data()), UCharCast(ser.data() + ser.size()));
1145 2 : }
1146 :
1147 : /** Schedule bytes to be sent to the transport. */
1148 49286 : void Send(Span<const std::byte> data) { Send(MakeUCharSpan(data)); }
1149 :
1150 : /** Schedule our ellswift key to be sent to the transport. */
1151 76 : void SendKey() { Send(m_cipher.GetOurPubKey()); }
1152 :
1153 : /** Schedule specified garbage to be sent to the transport. */
1154 76 : void SendGarbage(Span<const uint8_t> garbage)
1155 : {
1156 : // Remember the specified garbage (so we can use it as AAD).
1157 76 : m_sent_garbage.assign(garbage.begin(), garbage.end());
1158 : // Schedule it for sending.
1159 76 : Send(m_sent_garbage);
1160 76 : }
1161 :
1162 : /** Schedule garbage (of specified length) to be sent to the transport. */
1163 75 : void SendGarbage(size_t garbage_len)
1164 : {
1165 : // Generate random garbage and send it.
1166 75 : SendGarbage(g_insecure_rand_ctx.randbytes<uint8_t>(garbage_len));
1167 75 : }
1168 :
1169 : /** Schedule garbage (with valid random length) to be sent to the transport. */
1170 23 : void SendGarbage()
1171 : {
1172 23 : SendGarbage(InsecureRandRange(V2Transport::MAX_GARBAGE_LEN + 1));
1173 23 : }
1174 :
1175 : /** Schedule a message to be sent to us by the transport. */
1176 54 : void AddMessage(std::string m_type, std::vector<uint8_t> payload)
1177 : {
1178 54 : CSerializedNetMsg msg;
1179 54 : msg.m_type = std::move(m_type);
1180 54 : msg.data = std::move(payload);
1181 54 : m_msg_to_send.push_back(std::move(msg));
1182 54 : }
1183 :
1184 : /** Expect ellswift key to have been received from transport and process it.
1185 : *
1186 : * Many other V2TransportTester functions cannot be called until after ReceiveKey() has been
1187 : * called, as no encryption keys are set up before that point.
1188 : */
1189 76 : void ReceiveKey()
1190 : {
1191 : // When processing a key, enough bytes need to have been received already.
1192 76 : BOOST_REQUIRE(m_received.size() >= EllSwiftPubKey::size());
1193 : // Initialize the cipher using it (acting as the opposite side of the tested transport).
1194 76 : m_cipher.Initialize(MakeByteSpan(m_received).first(EllSwiftPubKey::size()), !m_test_initiator);
1195 : // Strip the processed bytes off the front of the receive buffer.
1196 76 : m_received.erase(m_received.begin(), m_received.begin() + EllSwiftPubKey::size());
1197 76 : }
1198 :
1199 : /** Schedule an encrypted packet with specified content/aad/ignore to be sent to transport
1200 : * (only after ReceiveKey). */
1201 49134 : void SendPacket(Span<const uint8_t> content, Span<const uint8_t> aad = {}, bool ignore = false)
1202 : {
1203 : // Use cipher to construct ciphertext.
1204 49134 : std::vector<std::byte> ciphertext;
1205 49134 : ciphertext.resize(content.size() + BIP324Cipher::EXPANSION);
1206 49134 : m_cipher.Encrypt(
1207 49134 : /*contents=*/MakeByteSpan(content),
1208 49134 : /*aad=*/MakeByteSpan(aad),
1209 49134 : /*ignore=*/ignore,
1210 49134 : /*output=*/ciphertext);
1211 : // Schedule it for sending.
1212 49134 : Send(ciphertext);
1213 49134 : }
1214 :
1215 : /** Schedule garbage terminator to be sent to the transport (only after ReceiveKey). */
1216 76 : void SendGarbageTerm()
1217 : {
1218 : // Schedule the garbage terminator to be sent.
1219 76 : Send(m_cipher.GetSendGarbageTerminator());
1220 76 : }
1221 :
1222 : /** Schedule version packet to be sent to the transport (only after ReceiveKey). */
1223 290 : void SendVersion(Span<const uint8_t> version_data = {}, bool vers_ignore = false)
1224 : {
1225 290 : Span<const std::uint8_t> aad;
1226 : // Set AAD to garbage only for first packet.
1227 290 : if (!m_sent_aad) aad = m_sent_garbage;
1228 290 : SendPacket(/*content=*/version_data, /*aad=*/aad, /*ignore=*/vers_ignore);
1229 290 : m_sent_aad = true;
1230 290 : }
1231 :
1232 : /** Expect a packet to have been received from transport, process it, and return its contents
1233 : * (only after ReceiveKey). Decoys are skipped. Optional associated authenticated data (AAD) is
1234 : * expected in the first received packet, no matter if that is a decoy or not. */
1235 128 : std::vector<uint8_t> ReceivePacket(Span<const std::byte> aad = {})
1236 : {
1237 128 : std::vector<uint8_t> contents;
1238 : // Loop as long as there are ignored packets that are to be skipped.
1239 128 : while (true) {
1240 : // When processing a packet, at least enough bytes for its length descriptor must be received.
1241 128 : BOOST_REQUIRE(m_received.size() >= BIP324Cipher::LENGTH_LEN);
1242 : // Decrypt the content length.
1243 128 : size_t size = m_cipher.DecryptLength(MakeByteSpan(Span{m_received}.first(BIP324Cipher::LENGTH_LEN)));
1244 : // Check that the full packet is in the receive buffer.
1245 128 : BOOST_REQUIRE(m_received.size() >= size + BIP324Cipher::EXPANSION);
1246 : // Decrypt the packet contents.
1247 128 : contents.resize(size);
1248 128 : bool ignore{false};
1249 128 : bool ret = m_cipher.Decrypt(
1250 128 : /*input=*/MakeByteSpan(
1251 128 : Span{m_received}.first(size + BIP324Cipher::EXPANSION).subspan(BIP324Cipher::LENGTH_LEN)),
1252 128 : /*aad=*/aad,
1253 : /*ignore=*/ignore,
1254 128 : /*contents=*/MakeWritableByteSpan(contents));
1255 128 : BOOST_CHECK(ret);
1256 : // Don't expect AAD in further packets.
1257 128 : aad = {};
1258 : // Strip the processed packet's bytes off the front of the receive buffer.
1259 128 : m_received.erase(m_received.begin(), m_received.begin() + size + BIP324Cipher::EXPANSION);
1260 : // Stop if the ignore bit is not set on this packet.
1261 128 : if (!ignore) break;
1262 : }
1263 128 : return contents;
1264 128 : }
1265 :
1266 : /** Expect garbage and garbage terminator to have been received, and process them (only after
1267 : * ReceiveKey). */
1268 74 : void ReceiveGarbage()
1269 : {
1270 : // Figure out the garbage length.
1271 : size_t garblen;
1272 151202 : for (garblen = 0; garblen <= V2Transport::MAX_GARBAGE_LEN; ++garblen) {
1273 151202 : BOOST_REQUIRE(m_received.size() >= garblen + BIP324Cipher::GARBAGE_TERMINATOR_LEN);
1274 151202 : auto term_span = MakeByteSpan(Span{m_received}.subspan(garblen, BIP324Cipher::GARBAGE_TERMINATOR_LEN));
1275 151202 : if (term_span == m_cipher.GetReceiveGarbageTerminator()) break;
1276 151128 : }
1277 : // Copy the garbage to a buffer.
1278 74 : m_recv_garbage.assign(m_received.begin(), m_received.begin() + garblen);
1279 : // Strip garbage + garbage terminator off the front of the receive buffer.
1280 74 : m_received.erase(m_received.begin(), m_received.begin() + garblen + BIP324Cipher::GARBAGE_TERMINATOR_LEN);
1281 74 : }
1282 :
1283 : /** Expect version packet to have been received, and process it (only after ReceiveKey). */
1284 74 : void ReceiveVersion()
1285 : {
1286 74 : auto contents = ReceivePacket(/*aad=*/MakeByteSpan(m_recv_garbage));
1287 : // Version packets from real BIP324 peers are expected to be empty, despite the fact that
1288 : // this class supports *sending* non-empty version packets (to test that BIP324 peers
1289 : // correctly ignore version packet contents).
1290 74 : BOOST_CHECK(contents.empty());
1291 74 : }
1292 :
1293 : /** Expect application packet to have been received, with specified short id and payload.
1294 : * (only after ReceiveKey). */
1295 3 : void ReceiveMessage(uint8_t short_id, Span<const uint8_t> payload)
1296 : {
1297 3 : auto ret = ReceivePacket();
1298 3 : BOOST_CHECK(ret.size() == payload.size() + 1);
1299 3 : BOOST_CHECK(ret[0] == short_id);
1300 3 : BOOST_CHECK(Span{ret}.subspan(1) == payload);
1301 3 : }
1302 :
1303 : /** Expect application packet to have been received, with specified 12-char message type and
1304 : * payload (only after ReceiveKey). */
1305 51 : void ReceiveMessage(const std::string& m_type, Span<const uint8_t> payload)
1306 : {
1307 51 : auto ret = ReceivePacket();
1308 51 : BOOST_REQUIRE(ret.size() == payload.size() + 1 + CMessageHeader::COMMAND_SIZE);
1309 51 : BOOST_CHECK(ret[0] == 0);
1310 663 : for (unsigned i = 0; i < 12; ++i) {
1311 612 : if (i < m_type.size()) {
1312 311 : BOOST_CHECK(ret[1 + i] == m_type[i]);
1313 311 : } else {
1314 301 : BOOST_CHECK(ret[1 + i] == 0);
1315 : }
1316 612 : }
1317 51 : BOOST_CHECK(Span{ret}.subspan(1 + CMessageHeader::COMMAND_SIZE) == payload);
1318 51 : }
1319 :
1320 : /** Schedule an encrypted packet with specified message type and payload to be sent to
1321 : * transport (only after ReceiveKey). */
1322 120 : void SendMessage(std::string mtype, Span<const uint8_t> payload)
1323 : {
1324 : // Construct contents consisting of 0x00 + 12-byte message type + payload.
1325 120 : std::vector<uint8_t> contents(1 + CMessageHeader::COMMAND_SIZE + payload.size());
1326 120 : std::copy(mtype.begin(), mtype.end(), reinterpret_cast<char*>(contents.data() + 1));
1327 120 : std::copy(payload.begin(), payload.end(), contents.begin() + 1 + CMessageHeader::COMMAND_SIZE);
1328 : // Send a packet with that as contents.
1329 120 : SendPacket(contents);
1330 120 : }
1331 :
1332 : /** Schedule an encrypted packet with specified short message id and payload to be sent to
1333 : * transport (only after ReceiveKey). */
1334 152 : void SendMessage(uint8_t short_id, Span<const uint8_t> payload)
1335 : {
1336 : // Construct contents consisting of short_id + payload.
1337 152 : std::vector<uint8_t> contents(1 + payload.size());
1338 152 : contents[0] = short_id;
1339 152 : std::copy(payload.begin(), payload.end(), contents.begin() + 1);
1340 : // Send a packet with that as contents.
1341 152 : SendPacket(contents);
1342 152 : }
1343 :
1344 : /** Test whether the transport's session ID matches the session ID we expect. */
1345 71 : void CompareSessionIDs() const
1346 : {
1347 71 : auto info = m_transport.GetInfo();
1348 71 : BOOST_CHECK(info.session_id);
1349 71 : BOOST_CHECK(uint256(MakeUCharSpan(m_cipher.GetSessionID())) == *info.session_id);
1350 71 : }
1351 :
1352 : /** Introduce a bit error in the data scheduled to be sent. */
1353 10 : void Damage()
1354 : {
1355 10 : m_to_send[InsecureRandRange(m_to_send.size())] ^= (uint8_t{1} << InsecureRandRange(8));
1356 10 : }
1357 : };
1358 :
1359 : } // namespace
1360 :
1361 149 : BOOST_AUTO_TEST_CASE(v2transport_test)
1362 : {
1363 : // A mostly normal scenario, testing a transport in initiator mode.
1364 11 : for (int i = 0; i < 10; ++i) {
1365 10 : V2TransportTester tester(true);
1366 10 : auto ret = tester.Interact();
1367 10 : BOOST_REQUIRE(ret && ret->empty());
1368 10 : tester.SendKey();
1369 10 : tester.SendGarbage();
1370 10 : tester.ReceiveKey();
1371 10 : tester.SendGarbageTerm();
1372 10 : tester.SendVersion();
1373 10 : ret = tester.Interact();
1374 10 : BOOST_REQUIRE(ret && ret->empty());
1375 10 : tester.ReceiveGarbage();
1376 10 : tester.ReceiveVersion();
1377 10 : tester.CompareSessionIDs();
1378 10 : auto msg_data_1 = g_insecure_rand_ctx.randbytes<uint8_t>(InsecureRandRange(100000));
1379 10 : auto msg_data_2 = g_insecure_rand_ctx.randbytes<uint8_t>(InsecureRandRange(1000));
1380 10 : tester.SendMessage(uint8_t(4), msg_data_1); // cmpctblock short id
1381 10 : tester.SendMessage(0, {}); // Invalidly encoded message
1382 10 : tester.SendMessage("tx", msg_data_2); // 12-character encoded message type
1383 10 : ret = tester.Interact();
1384 10 : BOOST_REQUIRE(ret && ret->size() == 3);
1385 10 : BOOST_CHECK((*ret)[0] && (*ret)[0]->m_type == "cmpctblock" && Span{(*ret)[0]->m_recv} == MakeByteSpan(msg_data_1));
1386 10 : BOOST_CHECK(!(*ret)[1]);
1387 10 : BOOST_CHECK((*ret)[2] && (*ret)[2]->m_type == "tx" && Span{(*ret)[2]->m_recv} == MakeByteSpan(msg_data_2));
1388 :
1389 : // Then send a message with a bit error, expecting failure. It's possible this failure does
1390 : // not occur immediately (when the length descriptor was modified), but it should come
1391 : // eventually, and no messages can be delivered anymore.
1392 10 : tester.SendMessage("bad", msg_data_1);
1393 10 : tester.Damage();
1394 10 : while (true) {
1395 10 : ret = tester.Interact();
1396 10 : if (!ret) break; // failure
1397 0 : BOOST_CHECK(ret->size() == 0); // no message can be delivered
1398 : // Send another message.
1399 0 : auto msg_data_3 = g_insecure_rand_ctx.randbytes<uint8_t>(InsecureRandRange(10000));
1400 0 : tester.SendMessage(uint8_t(12), msg_data_3); // getheaders short id
1401 0 : }
1402 10 : }
1403 :
1404 : // Normal scenario, with a transport in responder node.
1405 11 : for (int i = 0; i < 10; ++i) {
1406 10 : V2TransportTester tester(false);
1407 10 : tester.SendKey();
1408 10 : tester.SendGarbage();
1409 10 : auto ret = tester.Interact();
1410 10 : BOOST_REQUIRE(ret && ret->empty());
1411 10 : tester.ReceiveKey();
1412 10 : tester.SendGarbageTerm();
1413 10 : tester.SendVersion();
1414 10 : ret = tester.Interact();
1415 10 : BOOST_REQUIRE(ret && ret->empty());
1416 10 : tester.ReceiveGarbage();
1417 10 : tester.ReceiveVersion();
1418 10 : tester.CompareSessionIDs();
1419 10 : auto msg_data_1 = g_insecure_rand_ctx.randbytes<uint8_t>(InsecureRandRange(100000));
1420 10 : auto msg_data_2 = g_insecure_rand_ctx.randbytes<uint8_t>(InsecureRandRange(1000));
1421 10 : tester.SendMessage(uint8_t(14), msg_data_1); // inv short id
1422 10 : tester.SendMessage(uint8_t(19), msg_data_2); // pong short id
1423 10 : ret = tester.Interact();
1424 10 : BOOST_REQUIRE(ret && ret->size() == 2);
1425 10 : BOOST_CHECK((*ret)[0] && (*ret)[0]->m_type == "inv" && Span{(*ret)[0]->m_recv} == MakeByteSpan(msg_data_1));
1426 10 : BOOST_CHECK((*ret)[1] && (*ret)[1]->m_type == "pong" && Span{(*ret)[1]->m_recv} == MakeByteSpan(msg_data_2));
1427 :
1428 : // Then send a too-large message.
1429 10 : auto msg_data_3 = g_insecure_rand_ctx.randbytes<uint8_t>(4005000);
1430 10 : tester.SendMessage(uint8_t(11), msg_data_3); // getdata short id
1431 10 : ret = tester.Interact();
1432 10 : BOOST_CHECK(!ret);
1433 10 : }
1434 :
1435 : // Various valid but unusual scenarios.
1436 51 : for (int i = 0; i < 50; ++i) {
1437 : /** Whether an initiator or responder is being tested. */
1438 50 : bool initiator = InsecureRandBool();
1439 : /** Use either 0 bytes or the maximum possible (4095 bytes) garbage length. */
1440 50 : size_t garb_len = InsecureRandBool() ? 0 : V2Transport::MAX_GARBAGE_LEN;
1441 : /** How many decoy packets to send before the version packet. */
1442 50 : unsigned num_ignore_version = InsecureRandRange(10);
1443 : /** What data to send in the version packet (ignored by BIP324 peers, but reserved for future extensions). */
1444 50 : auto ver_data = g_insecure_rand_ctx.randbytes<uint8_t>(InsecureRandBool() ? 0 : InsecureRandRange(1000));
1445 : /** Whether to immediately send key and garbage out (required for responders, optional otherwise). */
1446 50 : bool send_immediately = !initiator || InsecureRandBool();
1447 : /** How many decoy packets to send before the first and second real message. */
1448 50 : unsigned num_decoys_1 = InsecureRandRange(1000), num_decoys_2 = InsecureRandRange(1000);
1449 50 : V2TransportTester tester(initiator);
1450 50 : if (send_immediately) {
1451 34 : tester.SendKey();
1452 34 : tester.SendGarbage(garb_len);
1453 34 : }
1454 50 : auto ret = tester.Interact();
1455 50 : BOOST_REQUIRE(ret && ret->empty());
1456 50 : if (!send_immediately) {
1457 16 : tester.SendKey();
1458 16 : tester.SendGarbage(garb_len);
1459 16 : }
1460 50 : tester.ReceiveKey();
1461 50 : tester.SendGarbageTerm();
1462 266 : for (unsigned v = 0; v < num_ignore_version; ++v) {
1463 216 : size_t ver_ign_data_len = InsecureRandBool() ? 0 : InsecureRandRange(1000);
1464 216 : auto ver_ign_data = g_insecure_rand_ctx.randbytes<uint8_t>(ver_ign_data_len);
1465 216 : tester.SendVersion(ver_ign_data, true);
1466 216 : }
1467 50 : tester.SendVersion(ver_data, false);
1468 50 : ret = tester.Interact();
1469 50 : BOOST_REQUIRE(ret && ret->empty());
1470 50 : tester.ReceiveGarbage();
1471 50 : tester.ReceiveVersion();
1472 50 : tester.CompareSessionIDs();
1473 23650 : for (unsigned d = 0; d < num_decoys_1; ++d) {
1474 23600 : auto decoy_data = g_insecure_rand_ctx.randbytes<uint8_t>(InsecureRandRange(1000));
1475 23600 : tester.SendPacket(/*content=*/decoy_data, /*aad=*/{}, /*ignore=*/true);
1476 23600 : }
1477 50 : auto msg_data_1 = g_insecure_rand_ctx.randbytes<uint8_t>(InsecureRandRange(MAX_PROTOCOL_MESSAGE_LENGTH));
1478 50 : tester.SendMessage(uint8_t(28), msg_data_1);
1479 25022 : for (unsigned d = 0; d < num_decoys_2; ++d) {
1480 24972 : auto decoy_data = g_insecure_rand_ctx.randbytes<uint8_t>(InsecureRandRange(1000));
1481 24972 : tester.SendPacket(/*content=*/decoy_data, /*aad=*/{}, /*ignore=*/true);
1482 24972 : }
1483 50 : auto msg_data_2 = g_insecure_rand_ctx.randbytes<uint8_t>(InsecureRandRange(1000));
1484 50 : tester.SendMessage(uint8_t(13), msg_data_2); // headers short id
1485 : // Send invalidly-encoded message
1486 50 : tester.SendMessage(std::string("blocktxn\x00\x00\x00a", CMessageHeader::COMMAND_SIZE), {});
1487 50 : tester.SendMessage("foobar", {}); // test receiving unknown message type
1488 50 : tester.AddMessage("barfoo", {}); // test sending unknown message type
1489 50 : ret = tester.Interact();
1490 50 : BOOST_REQUIRE(ret && ret->size() == 4);
1491 50 : BOOST_CHECK((*ret)[0] && (*ret)[0]->m_type == "addrv2" && Span{(*ret)[0]->m_recv} == MakeByteSpan(msg_data_1));
1492 50 : BOOST_CHECK((*ret)[1] && (*ret)[1]->m_type == "headers" && Span{(*ret)[1]->m_recv} == MakeByteSpan(msg_data_2));
1493 50 : BOOST_CHECK(!(*ret)[2]);
1494 100 : BOOST_CHECK((*ret)[3] && (*ret)[3]->m_type == "foobar" && (*ret)[3]->m_recv.empty());
1495 50 : tester.ReceiveMessage("barfoo", {});
1496 50 : }
1497 :
1498 : // Too long garbage (initiator).
1499 : {
1500 1 : V2TransportTester tester(true);
1501 1 : auto ret = tester.Interact();
1502 1 : BOOST_REQUIRE(ret && ret->empty());
1503 1 : tester.SendKey();
1504 1 : tester.SendGarbage(V2Transport::MAX_GARBAGE_LEN + 1);
1505 1 : tester.ReceiveKey();
1506 1 : tester.SendGarbageTerm();
1507 1 : ret = tester.Interact();
1508 1 : BOOST_CHECK(!ret);
1509 1 : }
1510 :
1511 : // Too long garbage (responder).
1512 : {
1513 1 : V2TransportTester tester(false);
1514 1 : tester.SendKey();
1515 1 : tester.SendGarbage(V2Transport::MAX_GARBAGE_LEN + 1);
1516 1 : auto ret = tester.Interact();
1517 1 : BOOST_REQUIRE(ret && ret->empty());
1518 1 : tester.ReceiveKey();
1519 1 : tester.SendGarbageTerm();
1520 1 : ret = tester.Interact();
1521 1 : BOOST_CHECK(!ret);
1522 1 : }
1523 :
1524 : // Send garbage that includes the first 15 garbage terminator bytes somewhere.
1525 : {
1526 1 : V2TransportTester tester(true);
1527 1 : auto ret = tester.Interact();
1528 1 : BOOST_REQUIRE(ret && ret->empty());
1529 1 : tester.SendKey();
1530 1 : tester.ReceiveKey();
1531 : /** The number of random garbage bytes before the included first 15 bytes of terminator. */
1532 1 : size_t len_before = InsecureRandRange(V2Transport::MAX_GARBAGE_LEN - 16 + 1);
1533 : /** The number of random garbage bytes after it. */
1534 1 : size_t len_after = InsecureRandRange(V2Transport::MAX_GARBAGE_LEN - 16 - len_before + 1);
1535 : // Construct len_before + 16 + len_after random bytes.
1536 1 : auto garbage = g_insecure_rand_ctx.randbytes<uint8_t>(len_before + 16 + len_after);
1537 : // Replace the designed 16 bytes in the middle with the to-be-sent garbage terminator.
1538 1 : auto garb_term = MakeUCharSpan(tester.GetCipher().GetSendGarbageTerminator());
1539 1 : std::copy(garb_term.begin(), garb_term.begin() + 16, garbage.begin() + len_before);
1540 : // Introduce a bit error in the last byte of that copied garbage terminator, making only
1541 : // the first 15 of them match.
1542 1 : garbage[len_before + 15] ^= (uint8_t(1) << InsecureRandRange(8));
1543 1 : tester.SendGarbage(garbage);
1544 1 : tester.SendGarbageTerm();
1545 1 : tester.SendVersion();
1546 1 : ret = tester.Interact();
1547 1 : BOOST_REQUIRE(ret && ret->empty());
1548 1 : tester.ReceiveGarbage();
1549 1 : tester.ReceiveVersion();
1550 1 : tester.CompareSessionIDs();
1551 1 : auto msg_data_1 = g_insecure_rand_ctx.randbytes<uint8_t>(MAX_PROTOCOL_MESSAGE_LENGTH); // test that receiving max size payload works
1552 1 : auto msg_data_2 = g_insecure_rand_ctx.randbytes<uint8_t>(MAX_PROTOCOL_MESSAGE_LENGTH); // test that sending max size payload works
1553 : // Send an unknown/invalid short ID. Valid Bitcoin IDs are [0, V2_BITCOIN_IDS.size()-1],
1554 : // valid Dash IDs are [128, 128+V2_DASH_IDS.size()-1]. Generate IDs outside these ranges.
1555 2 : tester.SendMessage([]() {
1556 1 : if (g_insecure_rand_ctx.randbool()) {
1557 1 : return static_cast<uint8_t>(InsecureRandRange(95) + 33); // Invalid Bitcoin range [33, 127]
1558 : } else {
1559 0 : return static_cast<uint8_t>(InsecureRandRange(87) + 169); // Invalid Dash range [169, 255]
1560 : }
1561 2 : }(), {});
1562 1 : tester.SendMessage(uint8_t(2), msg_data_1); // "block" short id
1563 1 : tester.AddMessage("blocktxn", msg_data_2); // schedule blocktxn to be sent to us
1564 1 : ret = tester.Interact();
1565 1 : BOOST_REQUIRE(ret && ret->size() == 2);
1566 1 : BOOST_CHECK(!(*ret)[0]);
1567 1 : BOOST_CHECK((*ret)[1] && (*ret)[1]->m_type == "block" && Span{(*ret)[1]->m_recv} == MakeByteSpan(msg_data_1));
1568 1 : tester.ReceiveMessage(uint8_t(3), msg_data_2); // "blocktxn" short id
1569 1 : }
1570 :
1571 : // Send correct network's V1 header
1572 : {
1573 1 : V2TransportTester tester(false);
1574 1 : tester.SendV1Version(Params().MessageStart());
1575 1 : auto ret = tester.Interact();
1576 1 : BOOST_CHECK(ret);
1577 1 : }
1578 :
1579 : // Send wrong network's V1 header
1580 : {
1581 1 : V2TransportTester tester(false);
1582 1 : tester.SendV1Version(CreateChainParams(*m_node.args, CBaseChainParams::MAIN)->MessageStart());
1583 1 : auto ret = tester.Interact();
1584 1 : BOOST_CHECK(!ret);
1585 1 : }
1586 1 : }
1587 :
1588 149 : BOOST_AUTO_TEST_CASE(v2_short_id_version_negotiation)
1589 : {
1590 : // Test that v2 short ID encoding respects peer protocol version.
1591 : // This ensures backwards compatibility when adding new short IDs.
1592 :
1593 : // Test 1: Baseline messages (short IDs 0-167) work with any v2-capable peer
1594 : {
1595 1 : V2TransportTester tester(true);
1596 1 : tester.GetTransport().SetPeerVersion(BIP324_DASH_BASELINE_VERSION); // v70235
1597 :
1598 1 : auto ret = tester.Interact();
1599 1 : BOOST_REQUIRE(ret && ret->empty());
1600 1 : tester.SendKey();
1601 1 : tester.SendGarbage();
1602 1 : tester.ReceiveKey();
1603 1 : tester.SendGarbageTerm();
1604 1 : tester.SendVersion();
1605 1 : ret = tester.Interact();
1606 1 : BOOST_REQUIRE(ret && ret->empty());
1607 1 : tester.ReceiveGarbage();
1608 1 : tester.ReceiveVersion();
1609 :
1610 : // SPORK (short ID 128) should use short encoding
1611 1 : auto msg_data = g_insecure_rand_ctx.randbytes<uint8_t>(100);
1612 1 : tester.AddMessage("spork", msg_data);
1613 1 : ret = tester.Interact();
1614 1 : BOOST_REQUIRE(ret && ret->empty());
1615 1 : tester.ReceiveMessage(uint8_t(128), msg_data);
1616 1 : }
1617 :
1618 : // Test 2: New short IDs (168+) require version negotiation
1619 : {
1620 : // Old peer (v70238) - doesn't know about PLATFORMBAN short ID 168
1621 1 : V2TransportTester tester_old(true);
1622 1 : tester_old.GetTransport().SetPeerVersion(70238);
1623 :
1624 1 : auto ret = tester_old.Interact();
1625 1 : BOOST_REQUIRE(ret && ret->empty());
1626 1 : tester_old.SendKey();
1627 1 : tester_old.SendGarbage();
1628 1 : tester_old.ReceiveKey();
1629 1 : tester_old.SendGarbageTerm();
1630 1 : tester_old.SendVersion();
1631 1 : ret = tester_old.Interact();
1632 1 : BOOST_REQUIRE(ret && ret->empty());
1633 1 : tester_old.ReceiveGarbage();
1634 1 : tester_old.ReceiveVersion();
1635 :
1636 : // Old peer gets long encoding for PLATFORMBAN
1637 1 : auto msg_data_old = g_insecure_rand_ctx.randbytes<uint8_t>(100);
1638 1 : tester_old.AddMessage("platformban", msg_data_old);
1639 1 : ret = tester_old.Interact();
1640 1 : BOOST_REQUIRE(ret && ret->empty());
1641 1 : tester_old.ReceiveMessage("platformban", msg_data_old); // long encoding
1642 :
1643 : // New peer (v70240) - knows about PLATFORMBAN short ID 168
1644 1 : V2TransportTester tester_new(true);
1645 : // Uses PROTOCOL_VERSION (70240) by default
1646 :
1647 1 : ret = tester_new.Interact();
1648 1 : BOOST_REQUIRE(ret && ret->empty());
1649 1 : tester_new.SendKey();
1650 1 : tester_new.SendGarbage();
1651 1 : tester_new.ReceiveKey();
1652 1 : tester_new.SendGarbageTerm();
1653 1 : tester_new.SendVersion();
1654 1 : ret = tester_new.Interact();
1655 1 : BOOST_REQUIRE(ret && ret->empty());
1656 1 : tester_new.ReceiveGarbage();
1657 1 : tester_new.ReceiveVersion();
1658 :
1659 : // New peer gets short encoding for PLATFORMBAN
1660 1 : auto msg_data_new = g_insecure_rand_ctx.randbytes<uint8_t>(100);
1661 1 : tester_new.AddMessage("platformban", msg_data_new);
1662 1 : ret = tester_new.Interact();
1663 1 : BOOST_REQUIRE(ret && ret->empty());
1664 1 : tester_new.ReceiveMessage(uint8_t(168), msg_data_new); // short encoding
1665 1 : }
1666 1 : }
1667 :
1668 146 : BOOST_AUTO_TEST_SUITE_END()
|