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