net.cpp
1 // Copyright (c) 2020-2022 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/net.h> 6 7 #include <net.h> 8 #include <net_processing.h> 9 #include <netaddress.h> 10 #include <netmessagemaker.h> 11 #include <node/connection_types.h> 12 #include <node/eviction.h> 13 #include <protocol.h> 14 #include <random.h> 15 #include <serialize.h> 16 #include <span.h> 17 18 #include <vector> 19 20 void ConnmanTestMsg::Handshake(CNode& node, 21 bool successfully_connected, 22 ServiceFlags remote_services, 23 ServiceFlags local_services, 24 int32_t version, 25 bool relay_txs) 26 { 27 auto& peerman{static_cast<PeerManager&>(*m_msgproc)}; 28 auto& connman{*this}; 29 30 peerman.InitializeNode(node, local_services); 31 FlushSendBuffer(node); // Drop the version message added by InitializeNode. 32 33 CSerializedNetMsg msg_version{ 34 NetMsg::Make(NetMsgType::VERSION, 35 version, // 36 Using<CustomUintFormatter<8>>(remote_services), // 37 int64_t{}, // dummy time 38 int64_t{}, // ignored service bits 39 CNetAddr::V1(CService{}), // dummy 40 int64_t{}, // ignored service bits 41 CNetAddr::V1(CService{}), // ignored 42 uint64_t{1}, // dummy nonce 43 std::string{}, // dummy subver 44 int32_t{}, // dummy starting_height 45 relay_txs), 46 }; 47 48 (void)connman.ReceiveMsgFrom(node, std::move(msg_version)); 49 node.fPauseSend = false; 50 connman.ProcessMessagesOnce(node); 51 peerman.SendMessages(&node); 52 FlushSendBuffer(node); // Drop the verack message added by SendMessages. 53 if (node.fDisconnect) return; 54 assert(node.nVersion == version); 55 assert(node.GetCommonVersion() == std::min(version, PROTOCOL_VERSION)); 56 CNodeStateStats statestats; 57 assert(peerman.GetNodeStateStats(node.GetId(), statestats)); 58 assert(statestats.m_relay_txs == (relay_txs && !node.IsBlockOnlyConn())); 59 assert(statestats.their_services == remote_services); 60 if (successfully_connected) { 61 CSerializedNetMsg msg_verack{NetMsg::Make(NetMsgType::VERACK)}; 62 (void)connman.ReceiveMsgFrom(node, std::move(msg_verack)); 63 node.fPauseSend = false; 64 connman.ProcessMessagesOnce(node); 65 peerman.SendMessages(&node); 66 assert(node.fSuccessfullyConnected == true); 67 } 68 } 69 70 void ConnmanTestMsg::NodeReceiveMsgBytes(CNode& node, Span<const uint8_t> msg_bytes, bool& complete) const 71 { 72 assert(node.ReceiveMsgBytes(msg_bytes, complete)); 73 if (complete) { 74 node.MarkReceivedMsgsForProcessing(); 75 } 76 } 77 78 void ConnmanTestMsg::FlushSendBuffer(CNode& node) const 79 { 80 LOCK(node.cs_vSend); 81 node.vSendMsg.clear(); 82 node.m_send_memusage = 0; 83 while (true) { 84 const auto& [to_send, _more, _msg_type] = node.m_transport->GetBytesToSend(false); 85 if (to_send.empty()) break; 86 node.m_transport->MarkBytesSent(to_send.size()); 87 } 88 } 89 90 bool ConnmanTestMsg::ReceiveMsgFrom(CNode& node, CSerializedNetMsg&& ser_msg) const 91 { 92 bool queued = node.m_transport->SetMessageToSend(ser_msg); 93 assert(queued); 94 bool complete{false}; 95 while (true) { 96 const auto& [to_send, _more, _msg_type] = node.m_transport->GetBytesToSend(false); 97 if (to_send.empty()) break; 98 NodeReceiveMsgBytes(node, to_send, complete); 99 node.m_transport->MarkBytesSent(to_send.size()); 100 } 101 return complete; 102 } 103 104 CNode* ConnmanTestMsg::ConnectNodePublic(PeerManager& peerman, const char* pszDest, ConnectionType conn_type) 105 { 106 CNode* node = ConnectNode(CAddress{}, pszDest, /*fCountFailure=*/false, conn_type, /*use_v2transport=*/true); 107 if (!node) return nullptr; 108 node->SetCommonVersion(PROTOCOL_VERSION); 109 peerman.InitializeNode(*node, ServiceFlags(NODE_NETWORK | NODE_WITNESS)); 110 node->fSuccessfullyConnected = true; 111 AddTestNode(*node); 112 return node; 113 } 114 115 std::vector<NodeEvictionCandidate> GetRandomNodeEvictionCandidates(int n_candidates, FastRandomContext& random_context) 116 { 117 std::vector<NodeEvictionCandidate> candidates; 118 candidates.reserve(n_candidates); 119 for (int id = 0; id < n_candidates; ++id) { 120 candidates.push_back({ 121 /*id=*/id, 122 /*m_connected=*/std::chrono::seconds{random_context.randrange(100)}, 123 /*m_min_ping_time=*/std::chrono::microseconds{random_context.randrange(100)}, 124 /*m_last_block_time=*/std::chrono::seconds{random_context.randrange(100)}, 125 /*m_last_tx_time=*/std::chrono::seconds{random_context.randrange(100)}, 126 /*fRelevantServices=*/random_context.randbool(), 127 /*m_relay_txs=*/random_context.randbool(), 128 /*fBloomFilter=*/random_context.randbool(), 129 /*nKeyedNetGroup=*/random_context.randrange(100), 130 /*prefer_evict=*/random_context.randbool(), 131 /*m_is_local=*/random_context.randbool(), 132 /*m_network=*/ALL_NETWORKS[random_context.randrange(ALL_NETWORKS.size())], 133 /*m_noban=*/false, 134 /*m_conn_type=*/ConnectionType::INBOUND, 135 }); 136 } 137 return candidates; 138 }