process_messages.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 <addrman.h>
   6  #include <banman.h>
   7  #include <consensus/consensus.h>
   8  #include <kernel/chainparams.h>
   9  #include <net.h>
  10  #include <net_processing.h>
  11  #include <node/mining_types.h>
  12  #include <primitives/block.h>
  13  #include <primitives/transaction.h>
  14  #include <protocol.h>
  15  #include <sync.h>
  16  #include <test/fuzz/FuzzedDataProvider.h>
  17  #include <test/fuzz/fuzz.h>
  18  #include <test/fuzz/util.h>
  19  #include <test/fuzz/util/net.h>
  20  #include <test/util/mining.h>
  21  #include <test/util/net.h>
  22  #include <test/util/random.h>
  23  #include <test/util/setup_common.h>
  24  #include <test/util/time.h>
  25  #include <test/util/validation.h>
  26  #include <util/time.h>
  27  #include <validation.h>
  28  #include <validationinterface.h>
  29  
  30  #include <functional>
  31  #include <ios>
  32  #include <memory>
  33  #include <optional>
  34  #include <string>
  35  #include <utility>
  36  #include <vector>
  37  
  38  namespace {
  39  TestingSetup* g_setup;
  40  
  41  void ResetChainman(TestingSetup& setup)
  42  {
  43      SetMockTime(setup.m_node.chainman->GetParams().GenesisBlock().Time());
  44      setup.m_node.chainman.reset();
  45      setup.m_make_chainman();
  46      setup.LoadVerifyActivateChainstate();
  47      node::BlockCreateOptions options;
  48      for (int i = 0; i < 2 * COINBASE_MATURITY; i++) {
  49          MineBlock(setup.m_node, options);
  50      }
  51  }
  52  } // namespace
  53  
  54  void initialize_process_messages()
  55  {
  56      static const auto testing_setup{
  57          MakeNoLogFileContext<TestingSetup>(
  58              /*chain_type=*/ChainType::REGTEST,
  59              {}),
  60      };
  61      g_setup = testing_setup.get();
  62      ResetChainman(*g_setup);
  63  }
  64  
  65  FUZZ_TARGET(process_messages, .init = initialize_process_messages)
  66  {
  67      SeedRandomStateForTest(SeedRand::ZEROS);
  68      FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
  69  
  70      auto& node{g_setup->m_node};
  71      auto& connman{static_cast<ConnmanTestMsg&>(*node.connman)};
  72      connman.Reset();
  73      auto& chainman{static_cast<TestChainstateManager&>(*node.chainman)};
  74      const auto block_index_size{WITH_LOCK(chainman.GetMutex(), return chainman.BlockIndex().size())};
  75      FakeNodeClock clock{1610000000s}; // any time to successfully reset ibd
  76      FakeSteadyClock steady_clock;
  77      chainman.ResetIbd();
  78      chainman.DisableNextWrite();
  79  
  80      // Reset, so that dangling pointers can be detected by sanitizers.
  81      node.banman.reset();
  82      node.addrman.reset();
  83      node.peerman.reset();
  84      node.addrman = std::make_unique<AddrMan>(*node.netgroupman, /*deterministic=*/true, /*consistency_check_ratio=*/0);
  85      node.peerman = PeerManager::make(connman, *node.addrman,
  86                                       /*banman=*/nullptr, chainman,
  87                                       *node.mempool, *node.warnings,
  88                                       PeerManager::Options{
  89                                           .reconcile_txs = true,
  90                                           .deterministic_rng = true,
  91                                       });
  92      connman.SetMsgProc(node.peerman.get());
  93      connman.SetAddrman(*node.addrman);
  94  
  95      node.validation_signals->RegisterValidationInterface(node.peerman.get());
  96  
  97      LOCK(NetEventsInterface::g_msgproc_mutex);
  98  
  99      std::vector<CNode*> peers;
 100      const auto num_peers_to_add = fuzzed_data_provider.ConsumeIntegralInRange(1, 3);
 101      for (int i = 0; i < num_peers_to_add; ++i) {
 102          peers.push_back(ConsumeNodeAsUniquePtr(fuzzed_data_provider, steady_clock, i).release());
 103          CNode& p2p_node = *peers.back();
 104  
 105          FillNode(fuzzed_data_provider, connman, p2p_node);
 106  
 107          connman.AddTestNode(p2p_node);
 108      }
 109  
 110      LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 30)
 111      {
 112          const std::string random_message_type{fuzzed_data_provider.ConsumeBytesAsString(CMessageHeader::MESSAGE_TYPE_SIZE).c_str()};
 113  
 114          clock.set(ConsumeTime(fuzzed_data_provider));
 115  
 116          CSerializedNetMsg net_msg;
 117          net_msg.m_type = random_message_type;
 118          net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider, MAX_PROTOCOL_MESSAGE_LENGTH);
 119  
 120          CNode& random_node = *PickValue(fuzzed_data_provider, peers);
 121  
 122          connman.FlushSendBuffer(random_node);
 123          (void)connman.ReceiveMsgFrom(random_node, std::move(net_msg));
 124  
 125          bool more_work{true};
 126          while (more_work) { // Ensure that every message is eventually processed in some way or another
 127              random_node.fPauseSend = false;
 128  
 129              try {
 130                  more_work = connman.ProcessMessagesOnce(random_node);
 131              } catch (const std::ios_base::failure&) {
 132              }
 133              node.peerman->SendMessages(random_node);
 134          }
 135      }
 136      node.validation_signals->SyncWithValidationInterfaceQueue();
 137      node.validation_signals->UnregisterValidationInterface(node.peerman.get());
 138      node.connman->StopNodes();
 139      if (block_index_size != WITH_LOCK(chainman.GetMutex(), return chainman.BlockIndex().size())) {
 140          // Reuse the global chainman, but reset it when it is dirty
 141          ResetChainman(*g_setup);
 142      }
 143  }
 144