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