LCOV - code coverage report
Current view: top level - src/test - net_peer_connection_tests.cpp (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 93.9 % 82 77
Test Date: 2024-11-04 05:10:19 Functions: 100.0 % 5 5
Branches: 52.8 % 356 188

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

Generated by: LCOV version 2.0-1