p2p_handshake.cpp raw

   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 <banman.h>
   6  #include <net.h>
   7  #include <net_processing.h>
   8  #include <protocol.h>
   9  #include <sync.h>
  10  #include <test/fuzz/FuzzedDataProvider.h>
  11  #include <test/fuzz/fuzz.h>
  12  #include <test/fuzz/util.h>
  13  #include <test/fuzz/util/net.h>
  14  #include <test/util/net.h>
  15  #include <test/util/setup_common.h>
  16  #include <test/util/time.h>
  17  #include <test/util/validation.h>
  18  #include <util/time.h>
  19  #include <validationinterface.h>
  20  
  21  #include <ios>
  22  #include <utility>
  23  #include <vector>
  24  
  25  namespace {
  26  TestingSetup* g_setup;
  27  
  28  void initialize()
  29  {
  30      static const auto testing_setup = MakeNoLogFileContext<TestingSetup>(
  31          /*chain_type=*/ChainType::REGTEST);
  32      g_setup = testing_setup.get();
  33  }
  34  } // namespace
  35  
  36  FUZZ_TARGET(p2p_handshake, .init = ::initialize)
  37  {
  38      SeedRandomStateForTest(SeedRand::ZEROS);
  39      FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
  40  
  41      auto& node{g_setup->m_node};
  42      auto& connman{static_cast<ConnmanTestMsg&>(*node.connman)};
  43      auto& chainman{static_cast<TestChainstateManager&>(*node.chainman)};
  44      FakeNodeClock clock{1610000000s}; // any time to successfully reset ibd
  45      FakeSteadyClock steady_clock;
  46      chainman.ResetIbd();
  47  
  48      node.banman.reset();
  49      node.addrman.reset();
  50      node.peerman.reset();
  51      node.addrman = std::make_unique<AddrMan>(
  52          *node.netgroupman, /*deterministic=*/true, /*consistency_check_ratio=*/0);
  53      node.peerman = PeerManager::make(connman, *node.addrman,
  54                                       /*banman=*/nullptr, chainman,
  55                                       *node.mempool, *node.warnings,
  56                                       PeerManager::Options{
  57                                           .reconcile_txs = true,
  58                                           .deterministic_rng = true,
  59                                       });
  60      connman.SetMsgProc(node.peerman.get());
  61      connman.SetAddrman(*node.addrman);
  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, steady_clock, i).release());
  69          connman.AddTestNode(*peers.back());
  70          node.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 += 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              node.peerman->SendMessages(connection);
 106          }
 107      }
 108  
 109      node.connman->StopNodes();
 110  }
 111