/ src / test / peerman_tests.cpp
peerman_tests.cpp
 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 <chainparams.h>
 6  #include <node/miner.h>
 7  #include <net_processing.h>
 8  #include <pow.h>
 9  #include <test/util/setup_common.h>
10  #include <validation.h>
11  
12  #include <boost/test/unit_test.hpp>
13  
14  BOOST_FIXTURE_TEST_SUITE(peerman_tests, RegTestingSetup)
15  
16  /** Window, in blocks, for connecting to NODE_NETWORK_LIMITED peers */
17  static constexpr int64_t NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS = 144;
18  
19  static void mineBlock(const node::NodeContext& node, std::chrono::seconds block_time)
20  {
21      auto curr_time = GetTime<std::chrono::seconds>();
22      node::BlockAssembler::Options options;
23      options.include_dummy_extranonce = true;
24      SetMockTime(block_time); // update time so the block is created with it
25      CBlock block = node::BlockAssembler{node.chainman->ActiveChainstate(), nullptr, options}.CreateNewBlock()->block;
26      while (!CheckProofOfWork(block.GetHash(), block.nBits, node.chainman->GetConsensus())) ++block.nNonce;
27      block.fChecked = true; // little speedup
28      SetMockTime(curr_time); // process block at current time
29      Assert(node.chainman->ProcessNewBlock(std::make_shared<const CBlock>(block), /*force_processing=*/true, /*min_pow_checked=*/true, nullptr));
30      node.validation_signals->SyncWithValidationInterfaceQueue(); // drain events queue
31  }
32  
33  // Verifying when network-limited peer connections are desirable based on the node's proximity to the tip
34  BOOST_AUTO_TEST_CASE(connections_desirable_service_flags)
35  {
36      std::unique_ptr<PeerManager> peerman = PeerManager::make(*m_node.connman, *m_node.addrman, nullptr, *m_node.chainman, *m_node.mempool, *m_node.warnings, {});
37      auto consensus = m_node.chainman->GetParams().GetConsensus();
38  
39      // Check we start connecting to full nodes
40      ServiceFlags peer_flags{NODE_WITNESS | NODE_NETWORK_LIMITED};
41      BOOST_CHECK(peerman->GetDesirableServiceFlags(peer_flags) == ServiceFlags(NODE_NETWORK | NODE_WITNESS));
42  
43      // Make peerman aware of the initial best block and verify we accept limited peers when we start close to the tip time.
44      auto tip = WITH_LOCK(::cs_main, return m_node.chainman->ActiveChain().Tip());
45      uint64_t tip_block_time = tip->GetBlockTime();
46      int tip_block_height = tip->nHeight;
47      peerman->SetBestBlock(tip_block_height, std::chrono::seconds{tip_block_time});
48  
49      SetMockTime(tip_block_time + 1); // Set node time to tip time
50      BOOST_CHECK(peerman->GetDesirableServiceFlags(peer_flags) == ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS));
51  
52      // Check we don't disallow limited peers connections when we are behind but still recoverable (below the connection safety window)
53      SetMockTime(GetTime<std::chrono::seconds>() + std::chrono::seconds{consensus.nPowTargetSpacing * (NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS - 1)});
54      BOOST_CHECK(peerman->GetDesirableServiceFlags(peer_flags) == ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS));
55  
56      // Check we disallow limited peers connections when we are further than the limited peers safety window
57      SetMockTime(GetTime<std::chrono::seconds>() + std::chrono::seconds{consensus.nPowTargetSpacing * 2});
58      BOOST_CHECK(peerman->GetDesirableServiceFlags(peer_flags) == ServiceFlags(NODE_NETWORK | NODE_WITNESS));
59  
60      // By now, we tested that the connections desirable services flags change based on the node's time proximity to the tip.
61      // Now, perform the same tests for when the node receives a block.
62      m_node.validation_signals->RegisterValidationInterface(peerman.get());
63  
64      // First, verify a block in the past doesn't enable limited peers connections
65      // At this point, our time is (NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS + 1) * 10 minutes ahead the tip's time.
66      mineBlock(m_node, /*block_time=*/std::chrono::seconds{tip_block_time + 1});
67      BOOST_CHECK(peerman->GetDesirableServiceFlags(peer_flags) == ServiceFlags(NODE_NETWORK | NODE_WITNESS));
68  
69      // Verify a block close to the tip enables limited peers connections
70      mineBlock(m_node, /*block_time=*/GetTime<std::chrono::seconds>());
71      BOOST_CHECK(peerman->GetDesirableServiceFlags(peer_flags) == ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS));
72  
73      // Lastly, verify the stale tip checks can disallow limited peers connections after not receiving blocks for a prolonged period.
74      SetMockTime(GetTime<std::chrono::seconds>() + std::chrono::seconds{consensus.nPowTargetSpacing * NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS + 1});
75      BOOST_CHECK(peerman->GetDesirableServiceFlags(peer_flags) == ServiceFlags(NODE_NETWORK | NODE_WITNESS));
76  }
77  
78  BOOST_AUTO_TEST_SUITE_END()