LCOV - code coverage report
Current view: top level - src/test - net_peer_connection_tests.cpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 81 82 98.8 %
Date: 2026-06-25 07:23:51 Functions: 14 14 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2023-present 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 <chainparams.h>
       6             : #include <compat/compat.h>
       7             : #include <net.h>
       8             : #include <net_processing.h>
       9             : #include <netaddress.h>
      10             : #include <netbase.h>
      11             : #include <netgroup.h>
      12             : #include <node/connection_types.h>
      13             : #include <protocol.h>
      14             : #include <random.h>
      15             : #include <test/util/logging.h>
      16             : #include <test/util/net.h>
      17             : #include <test/util/setup_common.h>
      18             : #include <tinyformat.h>
      19             : #include <version.h>
      20             : 
      21             : #include <algorithm>
      22             : #include <cstdint>
      23             : #include <memory>
      24             : #include <optional>
      25             : #include <string>
      26             : #include <vector>
      27             : 
      28             : #include <boost/test/unit_test.hpp>
      29             : 
      30             : struct LogIPsTestingSetup : public TestingSetup {
      31           1 :     LogIPsTestingSetup()
      32           1 :         : TestingSetup{CBaseChainParams::MAIN, /*extra_args=*/{"-logips"}} {}
      33             : };
      34             : 
      35         146 : BOOST_FIXTURE_TEST_SUITE(net_peer_connection_tests, LogIPsTestingSetup)
      36             : 
      37           3 : static CService ip(uint32_t i)
      38             : {
      39             :     struct in_addr s;
      40           3 :     s.s_addr = i;
      41           3 :     return CService{CNetAddr{s}, Params().GetDefaultPort()};
      42           0 : }
      43             : 
      44             : /** Create a peer and connect to it. If the optional `address` (IP/CJDNS only) isn't passed, a random address is created. */
      45           6 : static void AddPeer(NodeId& id, std::vector<CNode*>& nodes, PeerManager& peerman, ConnmanTestMsg& connman, ConnectionType conn_type, bool onion_peer = false, std::optional<std::string> address = std::nullopt)
      46             : {
      47           6 :     CAddress addr{};
      48             : 
      49           6 :     if (address.has_value()) {
      50           2 :         addr = CAddress{MaybeFlipIPv6toCJDNS(LookupNumeric(address.value(), Params().GetDefaultPort())), NODE_NONE};
      51           6 :     } else if (onion_peer) {
      52           1 :         auto tor_addr{g_insecure_rand_ctx.randbytes(ADDR_TORV3_SIZE)};
      53           1 :         BOOST_REQUIRE(addr.SetSpecial(OnionToString(tor_addr)));
      54           1 :     }
      55             : 
      56           9 :     while (!addr.IsLocal() && !addr.IsRoutable()) {
      57           3 :         addr = CAddress{ip(g_insecure_rand_ctx.randbits(32)), NODE_NONE};
      58             :     }
      59             : 
      60           6 :     BOOST_REQUIRE(addr.IsValid());
      61             : 
      62           6 :     const bool inbound_onion{onion_peer && conn_type == ConnectionType::INBOUND};
      63             : 
      64          12 :     nodes.emplace_back(new CNode{++id,
      65           6 :                                  /*sock=*/nullptr,
      66             :                                  addr,
      67             :                                  /*nKeyedNetGroupIn=*/0,
      68             :                                  /*nLocalHostNonceIn=*/0,
      69           6 :                                  CAddress{},
      70           6 :                                  /*addrNameIn=*/"",
      71           6 :                                  conn_type,
      72           6 :                                  /*inbound_onion=*/inbound_onion});
      73           6 :     CNode& node = *nodes.back();
      74           6 :     node.SetCommonVersion(PROTOCOL_VERSION);
      75             : 
      76           6 :     peerman.InitializeNode(node, ServiceFlags(NODE_NETWORK));
      77           6 :     node.fSuccessfullyConnected = true;
      78             : 
      79           6 :     connman.AddTestNode(node);
      80           6 : }
      81             : 
      82         148 : BOOST_AUTO_TEST_CASE(test_addnode_getaddednodeinfo_and_connection_detection)
      83             : {
      84           1 :     const auto& chainparams = Params();
      85           1 :     auto connman = std::make_unique<ConnmanTestMsg>(0x1337, 0x1337, *m_node.addrman, *m_node.netgroupman);
      86           1 :     auto peerman = MakePeerManager(*connman, m_node, /*banman=*/nullptr, chainparams, /*ignore_incoming_txs=*/false);
      87           1 :     NodeId id{0};
      88           1 :     std::vector<CNode*> nodes;
      89             : 
      90             :     // Connect a localhost peer.
      91             :     {
      92           1 :         ASSERT_DEBUG_LOG("Added connection to 127.0.0.1:9999 peer=1");
      93           1 :         AddPeer(id, nodes, *peerman, *connman, ConnectionType::MANUAL, /*onion_peer=*/false, /*address=*/"127.0.0.1");
      94           1 :         BOOST_REQUIRE(nodes.back() != nullptr);
      95           1 :     }
      96             : 
      97             :     // Call ConnectNode(), which is also called by RPC addnode onetry, for a localhost
      98             :     // address that resolves to multiple IPs, including that of the connected peer.
      99             :     // The connection attempt should consistently fail due to the check in ConnectNode().
     100          11 :     for (int i = 0; i < 10; ++i) {
     101          10 :         ASSERT_DEBUG_LOG("Not opening a connection to localhost, already connected to 127.0.0.1:9999");
     102          10 :         BOOST_CHECK(!connman->ConnectNodePublic(*peerman, "localhost", ConnectionType::MANUAL));
     103          10 :     }
     104             : 
     105             :     // Add 3 more peer connections.
     106           1 :     AddPeer(id, nodes, *peerman, *connman, ConnectionType::OUTBOUND_FULL_RELAY);
     107           1 :     AddPeer(id, nodes, *peerman, *connman, ConnectionType::BLOCK_RELAY, /*onion_peer=*/true);
     108           1 :     AddPeer(id, nodes, *peerman, *connman, ConnectionType::INBOUND);
     109             : 
     110             :     // Add a CJDNS peer connection.
     111           1 :     AddPeer(id, nodes, *peerman, *connman, ConnectionType::INBOUND, /*onion_peer=*/false,
     112           1 :             /*address=*/"[fc00:3344:5566:7788:9900:aabb:ccdd:eeff]:1234");
     113           1 :     BOOST_CHECK(nodes.back()->IsInboundConn());
     114           1 :     BOOST_CHECK_EQUAL(nodes.back()->ConnectedThroughNetwork(), Network::NET_CJDNS);
     115             : 
     116           1 :     BOOST_TEST_MESSAGE("Call AddNode() for all the peers");
     117           6 :     for (auto node : connman->TestNodes()) {
     118           5 :         BOOST_CHECK(connman->AddNode({/*m_added_node=*/node->addr.ToStringAddrPort(), /*m_use_v2transport=*/true}));
     119           5 :         BOOST_TEST_MESSAGE(strprintf("peer id=%s addr=%s", node->GetId(), node->addr.ToStringAddrPort()));
     120             :     }
     121             : 
     122           1 :     BOOST_TEST_MESSAGE("\nCall AddNode() with 2 addrs resolving to existing localhost addnode entry; neither should be added");
     123           1 :     BOOST_CHECK(!connman->AddNode({/*m_added_node=*/"127.0.0.1", /*m_use_v2transport=*/true}));
     124             :     // OpenBSD doesn't support the IPv4 shorthand notation with omitted zero-bytes.
     125             : #if !defined(__OpenBSD__)
     126           1 :     BOOST_CHECK(!connman->AddNode({/*m_added_node=*/"127.1", /*m_use_v2transport=*/true}));
     127             : #endif
     128             : 
     129           1 :     BOOST_TEST_MESSAGE("\nExpect GetAddedNodeInfo to return expected number of peers with `include_connected` true/false");
     130           1 :     BOOST_CHECK_EQUAL(connman->GetAddedNodeInfo(/*include_connected=*/true).size(), nodes.size());
     131           1 :     BOOST_CHECK(connman->GetAddedNodeInfo(/*include_connected=*/false).empty());
     132             : 
     133             :     // Test AddedNodesContain()
     134           6 :     for (auto node : connman->TestNodes()) {
     135           5 :         BOOST_CHECK(connman->AddedNodesContain(node->addr));
     136             :     }
     137           1 :     AddPeer(id, nodes, *peerman, *connman, ConnectionType::OUTBOUND_FULL_RELAY);
     138           1 :     BOOST_CHECK(!connman->AddedNodesContain(nodes.back()->addr));
     139             : 
     140           1 :     BOOST_TEST_MESSAGE("\nPrint GetAddedNodeInfo contents:");
     141           6 :     for (const auto& info : connman->GetAddedNodeInfo(/*include_connected=*/true)) {
     142           5 :         BOOST_TEST_MESSAGE(strprintf("\nadded node: %s", info.m_params.m_added_node));
     143           5 :         BOOST_TEST_MESSAGE(strprintf("connected: %s", info.fConnected));
     144           5 :         if (info.fConnected) {
     145           5 :             BOOST_TEST_MESSAGE(strprintf("IP address: %s", info.resolvedAddress.ToStringAddrPort()));
     146           5 :             BOOST_TEST_MESSAGE(strprintf("direction: %s", info.fInbound ? "inbound" : "outbound"));
     147           5 :         }
     148             :     }
     149             : 
     150           1 :     BOOST_TEST_MESSAGE("\nCheck that all connected peers are correctly detected as connected");
     151           7 :     for (auto node : connman->TestNodes()) {
     152           6 :         BOOST_CHECK(connman->AlreadyConnectedPublic(node->addr));
     153             :     }
     154             : 
     155             :     // Clean up
     156           7 :     for (auto node : connman->TestNodes()) {
     157           6 :         peerman->FinalizeNode(*node);
     158             :     }
     159           1 :     connman->ClearTestNodes();
     160           1 : }
     161             : 
     162         146 : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.16