Skip to content

Commit aff7d92

Browse files
committed
test: add coverage for peerman adaptive connections service flags
1 parent 6ed5360 commit aff7d92

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed

src/Makefile.test.include

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ BITCOIN_TESTS =\
117117
test/net_tests.cpp \
118118
test/netbase_tests.cpp \
119119
test/orphanage_tests.cpp \
120+
test/peerman_tests.cpp \
120121
test/pmt_tests.cpp \
121122
test/policy_fee_tests.cpp \
122123
test/policyestimator_tests.cpp \

src/test/peerman_tests.cpp

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

0 commit comments

Comments
 (0)