/ 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/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  }