p2p_handshake.cpp
1 // Copyright (c) 2020-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 <addrman.h> 6 #include <consensus/consensus.h> 7 #include <net.h> 8 #include <net_processing.h> 9 #include <node/warnings.h> 10 #include <protocol.h> 11 #include <script/script.h> 12 #include <sync.h> 13 #include <test/fuzz/FuzzedDataProvider.h> 14 #include <test/fuzz/fuzz.h> 15 #include <test/fuzz/util.h> 16 #include <test/fuzz/util/net.h> 17 #include <test/util/mining.h> 18 #include <test/util/net.h> 19 #include <test/util/setup_common.h> 20 #include <test/util/time.h> 21 #include <test/util/validation.h> 22 #include <util/time.h> 23 #include <validationinterface.h> 24 25 #include <ios> 26 #include <string> 27 #include <utility> 28 #include <vector> 29 30 namespace { 31 const TestingSetup* g_setup; 32 33 void initialize() 34 { 35 static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>( 36 /*chain_type=*/ChainType::REGTEST); 37 g_setup = testing_setup.get(); 38 } 39 } // namespace 40 41 FUZZ_TARGET(p2p_handshake, .init = ::initialize) 42 { 43 SeedRandomStateForTest(SeedRand::ZEROS); 44 FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); 45 46 auto& connman = static_cast<ConnmanTestMsg&>(*g_setup->m_node.connman); 47 auto& chainman = static_cast<TestChainstateManager&>(*g_setup->m_node.chainman); 48 NodeClockContext clock_ctx{1610000000s}; // any time to successfully reset ibd 49 chainman.ResetIbd(); 50 51 node::Warnings warnings{}; 52 auto netgroupman{NetGroupManager::NoAsmap()}; 53 AddrMan addrman{netgroupman, /*deterministic=*/true, /*consistency_check_ratio=*/0}; 54 auto peerman = PeerManager::make(connman, addrman, 55 /*banman=*/nullptr, chainman, 56 *g_setup->m_node.mempool, warnings, 57 PeerManager::Options{ 58 .reconcile_txs = true, 59 .deterministic_rng = true, 60 }); 61 connman.SetMsgProc(peerman.get()); 62 63 LOCK(NetEventsInterface::g_msgproc_mutex); 64 65 std::vector<CNode*> peers; 66 const auto num_peers_to_add = fuzzed_data_provider.ConsumeIntegralInRange(1, 3); 67 for (int i = 0; i < num_peers_to_add; ++i) { 68 peers.push_back(ConsumeNodeAsUniquePtr(fuzzed_data_provider, i).release()); 69 connman.AddTestNode(*peers.back()); 70 peerman->InitializeNode( 71 *peers.back(), 72 static_cast<ServiceFlags>(fuzzed_data_provider.ConsumeIntegral<uint64_t>())); 73 } 74 75 LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 100) 76 { 77 CNode& connection = *PickValue(fuzzed_data_provider, peers); 78 if (connection.fDisconnect || connection.fSuccessfullyConnected) { 79 // Skip if the connection was disconnected or if the version 80 // handshake was already completed. 81 continue; 82 } 83 84 clock_ctx += std::chrono::seconds{ 85 fuzzed_data_provider.ConsumeIntegralInRange<int64_t>( 86 -std::chrono::seconds{10min}.count(), // Allow mocktime to go backwards slightly 87 std::chrono::seconds{TIMEOUT_INTERVAL}.count()), 88 }; 89 90 CSerializedNetMsg net_msg; 91 net_msg.m_type = PickValue(fuzzed_data_provider, ALL_NET_MESSAGE_TYPES); 92 net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider, MAX_PROTOCOL_MESSAGE_LENGTH); 93 94 connman.FlushSendBuffer(connection); 95 (void)connman.ReceiveMsgFrom(connection, std::move(net_msg)); 96 97 bool more_work{true}; 98 while (more_work) { 99 connection.fPauseSend = false; 100 101 try { 102 more_work = connman.ProcessMessagesOnce(connection); 103 } catch (const std::ios_base::failure&) { 104 } 105 peerman->SendMessages(connection); 106 } 107 } 108 109 g_setup->m_node.connman->StopNodes(); 110 }