Bitcoin Core  29.1.0
P2P Digital Currency
net_peer_connection_tests.cpp
Go to the documentation of this file.
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 
34  : TestingSetup{ChainType::MAIN, {.extra_args = {"-logips"}}} {}
35 };
36 
37 BOOST_FIXTURE_TEST_SUITE(net_peer_connection_tests, LogIPsTestingSetup)
38 
39 static CService ip(uint32_t i)
40 {
41  struct in_addr s;
42  s.s_addr = i;
43  return CService{CNetAddr{s}, Params().GetDefaultPort()};
44 }
45 
48 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  CAddress addr{};
51 
52  if (address.has_value()) {
54  } else if (onion_peer) {
55  auto tor_addr{m_rng.randbytes(ADDR_TORV3_SIZE)};
56  BOOST_REQUIRE(addr.SetSpecial(OnionToString(tor_addr)));
57  }
58 
59  while (!addr.IsLocal() && !addr.IsRoutable()) {
60  addr = CAddress{ip(m_rng.randbits(32)), NODE_NONE};
61  }
62 
63  BOOST_REQUIRE(addr.IsValid());
64 
65  const bool inbound_onion{onion_peer && conn_type == ConnectionType::INBOUND};
66 
67  nodes.emplace_back(new CNode{++id,
68  /*sock=*/nullptr,
69  addr,
70  /*nKeyedNetGroupIn=*/0,
71  /*nLocalHostNonceIn=*/0,
72  CAddress{},
73  /*addrNameIn=*/"",
74  conn_type,
75  /*inbound_onion=*/inbound_onion});
76  CNode& node = *nodes.back();
77  node.SetCommonVersion(PROTOCOL_VERSION);
78 
80  node.fSuccessfullyConnected = true;
81 
82  connman.AddTestNode(node);
83 }
84 }; // struct PeerTest
85 
86 BOOST_FIXTURE_TEST_CASE(test_addnode_getaddednodeinfo_and_connection_detection, PeerTest)
87 {
88  auto connman = std::make_unique<ConnmanTestMsg>(0x1337, 0x1337, *m_node.addrman, *m_node.netgroupman, Params());
89  auto peerman = PeerManager::make(*connman, *m_node.addrman, nullptr, *m_node.chainman, *m_node.mempool, *m_node.warnings, {});
90  NodeId id{0};
91  std::vector<CNode*> nodes;
92 
93  // Connect a localhost peer.
94  {
95  ASSERT_DEBUG_LOG("Added connection to 127.0.0.1:8333 peer=1");
96  AddPeer(id, nodes, *peerman, *connman, ConnectionType::MANUAL, /*onion_peer=*/false, /*address=*/"127.0.0.1");
97  BOOST_REQUIRE(nodes.back() != nullptr);
98  }
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  for (int i = 0; i < 10; ++i) {
104  ASSERT_DEBUG_LOG("Not opening a connection to localhost, already connected to 127.0.0.1:8333");
105  BOOST_CHECK(!connman->ConnectNodePublic(*peerman, "localhost", ConnectionType::MANUAL));
106  }
107 
108  // Add 3 more peer connections.
109  AddPeer(id, nodes, *peerman, *connman, ConnectionType::OUTBOUND_FULL_RELAY);
110  AddPeer(id, nodes, *peerman, *connman, ConnectionType::BLOCK_RELAY, /*onion_peer=*/true);
111  AddPeer(id, nodes, *peerman, *connman, ConnectionType::INBOUND);
112 
113  // Add a CJDNS peer connection.
114  AddPeer(id, nodes, *peerman, *connman, ConnectionType::INBOUND, /*onion_peer=*/false,
115  /*address=*/"[fc00:3344:5566:7788:9900:aabb:ccdd:eeff]:1234");
116  BOOST_CHECK(nodes.back()->IsInboundConn());
117  BOOST_CHECK_EQUAL(nodes.back()->ConnectedThroughNetwork(), Network::NET_CJDNS);
118 
119  BOOST_TEST_MESSAGE("Call AddNode() for all the peers");
120  for (auto node : connman->TestNodes()) {
121  BOOST_CHECK(connman->AddNode({/*m_added_node=*/node->addr.ToStringAddrPort(), /*m_use_v2transport=*/true}));
122  BOOST_TEST_MESSAGE(strprintf("peer id=%s addr=%s", node->GetId(), node->addr.ToStringAddrPort()));
123  }
124 
125  BOOST_TEST_MESSAGE("\nCall AddNode() with 2 addrs resolving to existing localhost addnode entry; neither should be added");
126  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  BOOST_CHECK(!connman->AddNode({/*m_added_node=*/"127.1", /*m_use_v2transport=*/true}));
130 #endif
131 
132  BOOST_TEST_MESSAGE("\nExpect GetAddedNodeInfo to return expected number of peers with `include_connected` true/false");
133  BOOST_CHECK_EQUAL(connman->GetAddedNodeInfo(/*include_connected=*/true).size(), nodes.size());
134  BOOST_CHECK(connman->GetAddedNodeInfo(/*include_connected=*/false).empty());
135 
136  // Test AddedNodesContain()
137  for (auto node : connman->TestNodes()) {
138  BOOST_CHECK(connman->AddedNodesContain(node->addr));
139  }
140  AddPeer(id, nodes, *peerman, *connman, ConnectionType::OUTBOUND_FULL_RELAY);
141  BOOST_CHECK(!connman->AddedNodesContain(nodes.back()->addr));
142 
143  BOOST_TEST_MESSAGE("\nPrint GetAddedNodeInfo contents:");
144  for (const auto& info : connman->GetAddedNodeInfo(/*include_connected=*/true)) {
145  BOOST_TEST_MESSAGE(strprintf("\nadded node: %s", info.m_params.m_added_node));
146  BOOST_TEST_MESSAGE(strprintf("connected: %s", info.fConnected));
147  if (info.fConnected) {
148  BOOST_TEST_MESSAGE(strprintf("IP address: %s", info.resolvedAddress.ToStringAddrPort()));
149  BOOST_TEST_MESSAGE(strprintf("direction: %s", info.fInbound ? "inbound" : "outbound"));
150  }
151  }
152 
153  BOOST_TEST_MESSAGE("\nCheck that all connected peers are correctly detected as connected");
154  for (auto node : connman->TestNodes()) {
155  BOOST_CHECK(connman->AlreadyConnectedPublic(node->addr));
156  }
157 
158  // Clean up
159  for (auto node : connman->TestNodes()) {
160  peerman->FinalizeNode(*node);
161  }
162  connman->ClearTestNodes();
163 }
164 
std::vector< B > randbytes(size_t len) noexcept
Generate random bytes.
Definition: random.h:297
std::unique_ptr< node::Warnings > warnings
Manages all the node warnings.
Definition: context.h:91
ServiceFlags
nServices flags
Definition: protocol.h:309
Inbound connections are those initiated by a peer.
node::NodeContext m_node
Definition: bitcoin-gui.cpp:42
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1172
static constexpr size_t ADDR_TORV3_SIZE
Size of TORv3 address (in bytes).
Definition: netaddress.h:92
static std::unique_ptr< PeerManager > make(CConnman &connman, AddrMan &addrman, BanMan *banman, ChainstateManager &chainman, CTxMemPool &pool, node::Warnings &warnings, Options opts)
std::unique_ptr< const NetGroupManager > netgroupman
Definition: context.h:69
std::unique_ptr< AddrMan > addrman
Definition: context.h:66
CService MaybeFlipIPv6toCJDNS(const CService &service)
If an IPv6 address belongs to the address range used by the CJDNS network and the CJDNS network is re...
Definition: netbase.cpp:887
CService LookupNumeric(const std::string &name, uint16_t portDefault, DNSLookupFn dns_lookup_function)
Resolve a service string with a numeric IP to its first corresponding service.
Definition: netbase.cpp:220
These are the default connections that we use to connect with the network.
uint16_t GetDefaultPort() const
Definition: chainparams.h:95
std::unique_ptr< CTxMemPool > mempool
Definition: context.h:68
We open manual connections to addresses that users explicitly requested via the addnode RPC or the -a...
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
FastRandomContext m_rng
Definition: setup_common.h:68
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:530
BOOST_AUTO_TEST_SUITE_END()
A CService with information about it as peer.
Definition: protocol.h:366
static const int PROTOCOL_VERSION
network protocol versioning
int64_t NodeId
Definition: net.h:97
#define ASSERT_DEBUG_LOG(message)
Definition: logging.h:39
BOOST_FIXTURE_TEST_CASE(test_addnode_getaddednodeinfo_and_connection_detection, PeerTest)
Definition: messages.h:20
Network address.
Definition: netaddress.h:111
static CService ip(uint32_t i)
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
const CChainParams & Params()
Return the currently selected parameters.
uint64_t randbits(int bits) noexcept
Generate a random (bits)-bit integer.
Definition: random.h:204
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)
Create a peer and connect to it.
ConnectionType
Different types of connections to a peer.
std::string OnionToString(Span< const uint8_t > addr)
Definition: netaddress.cpp:573
Information about a peer.
Definition: net.h:672
virtual void InitializeNode(const CNode &node, ServiceFlags our_services)=0
Initialize a peer (setup state)
CJDNS.
Definition: netaddress.h:49
void AddTestNode(CNode &node)
Definition: net.h:54
std::unique_ptr< ChainstateManager > chainman
Definition: context.h:72
Testing setup that configures a complete environment.
Definition: setup_common.h:121
We use block-relay-only connections to help prevent against partition attacks.
#define BOOST_CHECK(expr)
Definition: object.cpp:17