@@ -40,6 +40,8 @@ CService ip(uint32_t i)
40
40
41
41
static NodeId id = 0 ;
42
42
43
+ void UpdateLastBlockAnnounceTime (NodeId node, int64_t time_in_seconds);
44
+
43
45
BOOST_FIXTURE_TEST_SUITE (DoS_tests, TestingSetup)
44
46
45
47
// Test eviction of an outbound peer whose chain never advances
@@ -87,6 +89,89 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
87
89
peerLogic->FinalizeNode (dummyNode1.GetId (), dummy);
88
90
}
89
91
92
+ void AddRandomOutboundPeer (std::vector<CNode *> &vNodes, PeerLogicValidation &peerLogic)
93
+ {
94
+ CAddress addr (ip (GetRandInt (0xffffffff )), NODE_NONE);
95
+ vNodes.emplace_back (new CNode (id++, ServiceFlags (NODE_NETWORK|NODE_WITNESS), 0 , INVALID_SOCKET, addr, 0 , 0 , CAddress (), " " , /* fInboundIn=*/ false ));
96
+ CNode &node = *vNodes.back ();
97
+ node.SetSendVersion (PROTOCOL_VERSION);
98
+
99
+ peerLogic.InitializeNode (&node);
100
+ node.nVersion = 1 ;
101
+ node.fSuccessfullyConnected = true ;
102
+
103
+ CConnmanTest::AddNode (node);
104
+ }
105
+
106
+ BOOST_AUTO_TEST_CASE (stale_tip_peer_management)
107
+ {
108
+ const Consensus::Params& consensusParams = Params ().GetConsensus ();
109
+ constexpr int nMaxOutbound = 8 ;
110
+ CConnman::Options options;
111
+ options.nMaxConnections = 125 ;
112
+ options.nMaxOutbound = nMaxOutbound;
113
+ options.nMaxFeeler = 1 ;
114
+
115
+ connman->Init (options);
116
+ std::vector<CNode *> vNodes;
117
+
118
+ // Mock some outbound peers
119
+ for (int i=0 ; i<nMaxOutbound; ++i) {
120
+ AddRandomOutboundPeer (vNodes, *peerLogic);
121
+ }
122
+
123
+ peerLogic->CheckForStaleTipAndEvictPeers (consensusParams);
124
+
125
+ // No nodes should be marked for disconnection while we have no extra peers
126
+ for (const CNode *node : vNodes) {
127
+ BOOST_CHECK (node->fDisconnect == false );
128
+ }
129
+
130
+ SetMockTime (GetTime () + 3 *consensusParams.nPowTargetSpacing + 1 );
131
+
132
+ // Now tip should definitely be stale, and we should look for an extra
133
+ // outbound peer
134
+ peerLogic->CheckForStaleTipAndEvictPeers (consensusParams);
135
+ BOOST_CHECK (connman->GetTryNewOutboundPeer ());
136
+
137
+ // Still no peers should be marked for disconnection
138
+ for (const CNode *node : vNodes) {
139
+ BOOST_CHECK (node->fDisconnect == false );
140
+ }
141
+
142
+ // If we add one more peer, something should get marked for eviction
143
+ // on the next check (since we're mocking the time to be in the future, the
144
+ // required time connected check should be satisfied).
145
+ AddRandomOutboundPeer (vNodes, *peerLogic);
146
+
147
+ peerLogic->CheckForStaleTipAndEvictPeers (consensusParams);
148
+ for (int i=0 ; i<nMaxOutbound; ++i) {
149
+ BOOST_CHECK (vNodes[i]->fDisconnect == false );
150
+ }
151
+ // Last added node should get marked for eviction
152
+ BOOST_CHECK (vNodes.back ()->fDisconnect == true );
153
+
154
+ vNodes.back ()->fDisconnect = false ;
155
+
156
+ // Update the last announced block time for the last
157
+ // peer, and check that the next newest node gets evicted.
158
+ UpdateLastBlockAnnounceTime (vNodes.back ()->GetId (), GetTime ());
159
+
160
+ peerLogic->CheckForStaleTipAndEvictPeers (consensusParams);
161
+ for (int i=0 ; i<nMaxOutbound-1 ; ++i) {
162
+ BOOST_CHECK (vNodes[i]->fDisconnect == false );
163
+ }
164
+ BOOST_CHECK (vNodes[nMaxOutbound-1 ]->fDisconnect == true );
165
+ BOOST_CHECK (vNodes.back ()->fDisconnect == false );
166
+
167
+ bool dummy;
168
+ for (const CNode *node : vNodes) {
169
+ peerLogic->FinalizeNode (node->GetId (), dummy);
170
+ }
171
+
172
+ CConnmanTest::ClearNodes ();
173
+ }
174
+
90
175
BOOST_AUTO_TEST_CASE (DoS_banning)
91
176
{
92
177
std::atomic<bool > interruptDummy (false );
0 commit comments