peerman_tests.cpp raw

   1  // Copyright (c) 2024-present The Bitcoin Core developers
   2  // Distributed under the MIT software license, see the accompanying
   3  // file COPYING or https://www.opensource.org/licenses/mit-license.php.
   4  
   5  #include <chain.h>
   6  #include <chainparams.h>
   7  #include <consensus/params.h>
   8  #include <interfaces/mining.h>
   9  #include <net_processing.h>
  10  #include <pow.h>
  11  #include <primitives/block.h>
  12  #include <protocol.h>
  13  #include <sync.h>
  14  #include <test/util/setup_common.h>
  15  #include <test/util/time.h>
  16  #include <util/check.h>
  17  #include <validation.h>
  18  #include <validationinterface.h>
  19  
  20  #include <boost/test/unit_test.hpp>
  21  
  22  #include <cstdint>
  23  #include <memory>
  24  
  25  BOOST_FIXTURE_TEST_SUITE(peerman_tests, RegTestingSetup)
  26  
  27  /** Window, in blocks, for connecting to NODE_NETWORK_LIMITED peers */
  28  static constexpr int64_t NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS = 144;
  29  
  30  static void mineBlock(node::NodeContext& node, FakeNodeClock& clock, std::chrono::seconds block_time)
  31  {
  32      auto curr_time = GetTime<std::chrono::seconds>();
  33      clock.set(block_time); // update time so the block is created with it
  34      auto mining{interfaces::MakeMining(node)};
  35      auto block_template{mining->createNewBlock({}, /*cooldown=*/false)};
  36      BOOST_REQUIRE(block_template);
  37      CBlock block{block_template->getBlock()};
  38      while (!CheckProofOfWork(block.GetHash(), block.nBits, node.chainman->GetConsensus())) ++block.nNonce;
  39      block.fChecked = true; // little speedup
  40      clock.set(curr_time); // process block at current time
  41      Assert(node.chainman->ProcessNewBlock(std::make_shared<const CBlock>(block), /*force_processing=*/true, /*min_pow_checked=*/true, nullptr));
  42      node.validation_signals->SyncWithValidationInterfaceQueue(); // drain events queue
  43  }
  44  
  45  // Verifying when network-limited peer connections are desirable based on the node's proximity to the tip
  46  BOOST_AUTO_TEST_CASE(connections_desirable_service_flags)
  47  {
  48      FakeNodeClock clock{};
  49      std::unique_ptr<PeerManager> peerman = PeerManager::make(*m_node.connman, *m_node.addrman, nullptr, *m_node.chainman, *m_node.mempool, *m_node.warnings, {});
  50      auto consensus = m_node.chainman->GetParams().GetConsensus();
  51  
  52      // Check we start connecting to full nodes
  53      ServiceFlags peer_flags{NODE_WITNESS | NODE_NETWORK_LIMITED};
  54      BOOST_CHECK(peerman->GetDesirableServiceFlags(peer_flags) == ServiceFlags(NODE_NETWORK | NODE_WITNESS));
  55  
  56      // Make peerman aware of the initial best block and verify we accept limited peers when we start close to the tip time.
  57      auto tip = WITH_LOCK(::cs_main, return m_node.chainman->ActiveChain().Tip());
  58      uint64_t tip_block_time = tip->GetBlockTime();
  59      int tip_block_height = tip->nHeight;
  60      peerman->SetBestBlock(tip_block_height, std::chrono::seconds{tip_block_time});
  61  
  62      clock.set(std::chrono::seconds{tip_block_time + 1}); // Set node time to tip time
  63      BOOST_CHECK(peerman->GetDesirableServiceFlags(peer_flags) == ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS));
  64  
  65      // Check we don't disallow limited peers connections when we are behind but still recoverable (below the connection safety window)
  66      clock += std::chrono::seconds{consensus.nPowTargetSpacing * (NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS - 1)};
  67      BOOST_CHECK(peerman->GetDesirableServiceFlags(peer_flags) == ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS));
  68  
  69      // Check we disallow limited peers connections when we are further than the limited peers safety window
  70      clock += std::chrono::seconds{consensus.nPowTargetSpacing * 2};
  71      BOOST_CHECK(peerman->GetDesirableServiceFlags(peer_flags) == ServiceFlags(NODE_NETWORK | NODE_WITNESS));
  72  
  73      // By now, we tested that the connections desirable services flags change based on the node's time proximity to the tip.
  74      // Now, perform the same tests for when the node receives a block.
  75      m_node.validation_signals->RegisterValidationInterface(peerman.get());
  76  
  77      // First, verify a block in the past doesn't enable limited peers connections
  78      // At this point, our time is (NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS + 1) * 10 minutes ahead the tip's time.
  79      mineBlock(m_node, clock, /*block_time=*/std::chrono::seconds{tip_block_time + 1});
  80      BOOST_CHECK(peerman->GetDesirableServiceFlags(peer_flags) == ServiceFlags(NODE_NETWORK | NODE_WITNESS));
  81  
  82      // Verify a block close to the tip enables limited peers connections
  83      mineBlock(m_node, clock, /*block_time=*/GetTime<std::chrono::seconds>());
  84      BOOST_CHECK(peerman->GetDesirableServiceFlags(peer_flags) == ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS));
  85  
  86      // Lastly, verify the stale tip checks can disallow limited peers connections after not receiving blocks for a prolonged period.
  87      clock += std::chrono::seconds{consensus.nPowTargetSpacing * NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS + 1};
  88      BOOST_CHECK(peerman->GetDesirableServiceFlags(peer_flags) == ServiceFlags(NODE_NETWORK | NODE_WITNESS));
  89  }
  90  
  91  BOOST_AUTO_TEST_SUITE_END()
  92