Bitcoin Core 28.0.0
P2P Digital Currency
Loading...
Searching...
No Matches
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>
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>
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
37BOOST_FIXTURE_TEST_SUITE(net_peer_connection_tests, LogIPsTestingSetup)
38
39static 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
47static 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)
48{
49 CAddress addr{};
50
51 if (address.has_value()) {
52 addr = CAddress{MaybeFlipIPv6toCJDNS(LookupNumeric(address.value(), Params().GetDefaultPort())), NODE_NONE};
53 } else if (onion_peer) {
55 BOOST_REQUIRE(addr.SetSpecial(OnionToString(tor_addr)));
56 }
57
58 while (!addr.IsLocal() && !addr.IsRoutable()) {
60 }
61
62 BOOST_REQUIRE(addr.IsValid());
63
64 const bool inbound_onion{onion_peer && conn_type == ConnectionType::INBOUND};
65
66 nodes.emplace_back(new CNode{++id,
67 /*sock=*/nullptr,
68 addr,
69 /*nKeyedNetGroupIn=*/0,
70 /*nLocalHostNonceIn=*/0,
71 CAddress{},
72 /*addrNameIn=*/"",
73 conn_type,
74 /*inbound_onion=*/inbound_onion});
75 CNode& node = *nodes.back();
76 node.SetCommonVersion(PROTOCOL_VERSION);
77
79 node.fSuccessfullyConnected = true;
80
81 connman.AddTestNode(node);
82}
83
84BOOST_AUTO_TEST_CASE(test_addnode_getaddednodeinfo_and_connection_detection)
85{
86 auto connman = std::make_unique<ConnmanTestMsg>(0x1337, 0x1337, *m_node.addrman, *m_node.netgroupman, Params());
87 auto peerman = PeerManager::make(*connman, *m_node.addrman, nullptr, *m_node.chainman, *m_node.mempool, *m_node.warnings, {});
88 NodeId id{0};
89 std::vector<CNode*> nodes;
90
91 // Connect a localhost peer.
92 {
93 ASSERT_DEBUG_LOG("Added connection to 127.0.0.1:8333 peer=1");
94 AddPeer(id, nodes, *peerman, *connman, ConnectionType::MANUAL, /*onion_peer=*/false, /*address=*/"127.0.0.1");
95 BOOST_REQUIRE(nodes.back() != nullptr);
96 }
97
98 // Call ConnectNode(), which is also called by RPC addnode onetry, for a localhost
99 // address that resolves to multiple IPs, including that of the connected peer.
100 // The connection attempt should consistently fail due to the check in ConnectNode().
101 for (int i = 0; i < 10; ++i) {
102 ASSERT_DEBUG_LOG("Not opening a connection to localhost, already connected to 127.0.0.1:8333");
103 BOOST_CHECK(!connman->ConnectNodePublic(*peerman, "localhost", ConnectionType::MANUAL));
104 }
105
106 // Add 3 more peer connections.
107 AddPeer(id, nodes, *peerman, *connman, ConnectionType::OUTBOUND_FULL_RELAY);
108 AddPeer(id, nodes, *peerman, *connman, ConnectionType::BLOCK_RELAY, /*onion_peer=*/true);
109 AddPeer(id, nodes, *peerman, *connman, ConnectionType::INBOUND);
110
111 // Add a CJDNS peer connection.
112 AddPeer(id, nodes, *peerman, *connman, ConnectionType::INBOUND, /*onion_peer=*/false,
113 /*address=*/"[fc00:3344:5566:7788:9900:aabb:ccdd:eeff]:1234");
114 BOOST_CHECK(nodes.back()->IsInboundConn());
115 BOOST_CHECK_EQUAL(nodes.back()->ConnectedThroughNetwork(), Network::NET_CJDNS);
116
117 BOOST_TEST_MESSAGE("Call AddNode() for all the peers");
118 for (auto node : connman->TestNodes()) {
119 BOOST_CHECK(connman->AddNode({/*m_added_node=*/node->addr.ToStringAddrPort(), /*m_use_v2transport=*/true}));
120 BOOST_TEST_MESSAGE(strprintf("peer id=%s addr=%s", node->GetId(), node->addr.ToStringAddrPort()));
121 }
122
123 BOOST_TEST_MESSAGE("\nCall AddNode() with 2 addrs resolving to existing localhost addnode entry; neither should be added");
124 BOOST_CHECK(!connman->AddNode({/*m_added_node=*/"127.0.0.1", /*m_use_v2transport=*/true}));
125 // OpenBSD doesn't support the IPv4 shorthand notation with omitted zero-bytes.
126#if !defined(__OpenBSD__)
127 BOOST_CHECK(!connman->AddNode({/*m_added_node=*/"127.1", /*m_use_v2transport=*/true}));
128#endif
129
130 BOOST_TEST_MESSAGE("\nExpect GetAddedNodeInfo to return expected number of peers with `include_connected` true/false");
131 BOOST_CHECK_EQUAL(connman->GetAddedNodeInfo(/*include_connected=*/true).size(), nodes.size());
132 BOOST_CHECK(connman->GetAddedNodeInfo(/*include_connected=*/false).empty());
133
134 // Test AddedNodesContain()
135 for (auto node : connman->TestNodes()) {
136 BOOST_CHECK(connman->AddedNodesContain(node->addr));
137 }
138 AddPeer(id, nodes, *peerman, *connman, ConnectionType::OUTBOUND_FULL_RELAY);
139 BOOST_CHECK(!connman->AddedNodesContain(nodes.back()->addr));
140
141 BOOST_TEST_MESSAGE("\nPrint GetAddedNodeInfo contents:");
142 for (const auto& info : connman->GetAddedNodeInfo(/*include_connected=*/true)) {
143 BOOST_TEST_MESSAGE(strprintf("\nadded node: %s", info.m_params.m_added_node));
144 BOOST_TEST_MESSAGE(strprintf("connected: %s", info.fConnected));
145 if (info.fConnected) {
146 BOOST_TEST_MESSAGE(strprintf("IP address: %s", info.resolvedAddress.ToStringAddrPort()));
147 BOOST_TEST_MESSAGE(strprintf("direction: %s", info.fInbound ? "inbound" : "outbound"));
148 }
149 }
150
151 BOOST_TEST_MESSAGE("\nCheck that all connected peers are correctly detected as connected");
152 for (auto node : connman->TestNodes()) {
153 BOOST_CHECK(connman->AlreadyConnectedPublic(node->addr));
154 }
155
156 // Clean up
157 for (auto node : connman->TestNodes()) {
158 peerman->FinalizeNode(*node);
159 }
160 connman->ClearTestNodes();
161}
162
node::NodeContext m_node
const CChainParams & Params()
Return the currently selected parameters.
ChainType
Definition chaintype.h:11
A CService with information about it as peer.
Definition protocol.h:367
uint16_t GetDefaultPort() const
Definition chainparams.h:95
Network address.
Definition netaddress.h:112
Information about a peer.
Definition net.h:670
A combination of a network address (CNetAddr) and a (TCP) port.
Definition netaddress.h:531
virtual void InitializeNode(const CNode &node, ServiceFlags our_services)=0
Initialize a peer (setup state)
static std::unique_ptr< PeerManager > make(CConnman &connman, AddrMan &addrman, BanMan *banman, ChainstateManager &chainman, CTxMemPool &pool, node::Warnings &warnings, Options opts)
std::vector< B > randbytes(size_t len) noexcept
Generate random bytes.
Definition random.h:297
uint64_t randbits(int bits) noexcept
Generate a random (bits)-bit integer.
Definition random.h:204
ConnectionType
Different types of connections to a peer.
@ BLOCK_RELAY
We use block-relay-only connections to help prevent against partition attacks.
@ MANUAL
We open manual connections to addresses that users explicitly requested via the addnode RPC or the -a...
@ OUTBOUND_FULL_RELAY
These are the default connections that we use to connect with the network.
@ INBOUND
Inbound connections are those initiated by a peer.
BOOST_AUTO_TEST_SUITE_END()
int64_t NodeId
Definition net.h:97
BOOST_AUTO_TEST_CASE(test_addnode_getaddednodeinfo_and_connection_detection)
static CService ip(uint32_t i)
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)
Create a peer and connect to it.
std::string OnionToString(Span< const uint8_t > addr)
static constexpr size_t ADDR_TORV3_SIZE
Size of TORv3 address (in bytes).
Definition netaddress.h:92
@ NET_CJDNS
CJDNS.
Definition netaddress.h:49
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:881
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
#define BOOST_CHECK_EQUAL(v1, v2)
Definition object.cpp:18
#define BOOST_CHECK(expr)
Definition object.cpp:17
ServiceFlags
nServices flags
Definition protocol.h:309
@ NODE_NONE
Definition protocol.h:312
@ NODE_WITNESS
Definition protocol.h:320
@ NODE_NETWORK
Definition protocol.h:315
static const int PROTOCOL_VERSION
network protocol versioning
void AddTestNode(CNode &node)
Definition net.h:53
Testing setup that configures a complete environment.
std::unique_ptr< CTxMemPool > mempool
Definition context.h:65
std::unique_ptr< AddrMan > addrman
Definition context.h:63
std::unique_ptr< ChainstateManager > chainman
Definition context.h:69
std::unique_ptr< node::Warnings > warnings
Manages all the node warnings.
Definition context.h:88
std::unique_ptr< const NetGroupManager > netgroupman
Definition context.h:66
#define ASSERT_DEBUG_LOG(message)
Definition logging.h:39
FastRandomContext g_insecure_rand_ctx
This global and the helpers that use it are not thread-safe.
Definition random.cpp:14
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...