Branch data Line data Source code
# 1 : : // Copyright (c) 2011-2021 The Bitcoin Core developers
# 2 : : // Distributed under the MIT software license, see the accompanying
# 3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 4 : :
# 5 : : // Unit tests for denial-of-service detection/prevention code
# 6 : :
# 7 : : #include <arith_uint256.h>
# 8 : : #include <banman.h>
# 9 : : #include <chainparams.h>
# 10 : : #include <net.h>
# 11 : : #include <net_processing.h>
# 12 : : #include <pubkey.h>
# 13 : : #include <script/sign.h>
# 14 : : #include <script/signingprovider.h>
# 15 : : #include <script/standard.h>
# 16 : : #include <serialize.h>
# 17 : : #include <test/util/net.h>
# 18 : : #include <test/util/setup_common.h>
# 19 : : #include <txorphanage.h>
# 20 : : #include <util/string.h>
# 21 : : #include <util/system.h>
# 22 : : #include <util/time.h>
# 23 : : #include <validation.h>
# 24 : :
# 25 : : #include <array>
# 26 : : #include <stdint.h>
# 27 : :
# 28 : : #include <boost/test/unit_test.hpp>
# 29 : :
# 30 : : static CService ip(uint32_t i)
# 31 : 34 : {
# 32 : 34 : struct in_addr s;
# 33 : 34 : s.s_addr = i;
# 34 : 34 : return CService(CNetAddr(s), Params().GetDefaultPort());
# 35 : 34 : }
# 36 : :
# 37 : : void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds);
# 38 : :
# 39 : : BOOST_FIXTURE_TEST_SUITE(denialofservice_tests, TestingSetup)
# 40 : :
# 41 : : // Test eviction of an outbound peer whose chain never advances
# 42 : : // Mock a node connection, and use mocktime to simulate a peer
# 43 : : // which never sends any headers messages. PeerLogic should
# 44 : : // decide to evict that outbound peer, after the appropriate timeouts.
# 45 : : // Note that we protect 4 outbound nodes from being subject to
# 46 : : // this logic; this test takes advantage of that protection only
# 47 : : // being applied to nodes which send headers with sufficient
# 48 : : // work.
# 49 : : BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
# 50 : 2 : {
# 51 : 2 : const CChainParams& chainparams = Params();
# 52 : 2 : auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
# 53 : : // Disable inactivity checks for this test to avoid interference
# 54 : 2 : static_cast<ConnmanTestMsg*>(connman.get())->SetPeerConnectTimeout(99999s);
# 55 : 2 : auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr,
# 56 : 2 : *m_node.chainman, *m_node.mempool, false);
# 57 : :
# 58 : : // Mock an outbound peer
# 59 : 2 : CAddress addr1(ip(0xa0b0c001), NODE_NONE);
# 60 : 2 : NodeId id{0};
# 61 : 2 : CNode dummyNode1{id++,
# 62 : 2 : ServiceFlags(NODE_NETWORK | NODE_WITNESS),
# 63 : 2 : /*sock=*/nullptr,
# 64 : 2 : addr1,
# 65 : 2 : /*nKeyedNetGroupIn=*/0,
# 66 : 2 : /*nLocalHostNonceIn=*/0,
# 67 : 2 : CAddress(),
# 68 : 2 : /*addrNameIn=*/"",
# 69 : 2 : ConnectionType::OUTBOUND_FULL_RELAY,
# 70 : 2 : /*inbound_onion=*/false};
# 71 : 2 : dummyNode1.SetCommonVersion(PROTOCOL_VERSION);
# 72 : :
# 73 : 2 : peerLogic->InitializeNode(&dummyNode1);
# 74 : 2 : dummyNode1.fSuccessfullyConnected = true;
# 75 : :
# 76 : : // This test requires that we have a chain with non-zero work.
# 77 : 2 : {
# 78 : 2 : LOCK(cs_main);
# 79 : 2 : BOOST_CHECK(m_node.chainman->ActiveChain().Tip() != nullptr);
# 80 : 2 : BOOST_CHECK(m_node.chainman->ActiveChain().Tip()->nChainWork > 0);
# 81 : 2 : }
# 82 : :
# 83 : : // Test starts here
# 84 : 2 : {
# 85 : 2 : LOCK(dummyNode1.cs_sendProcessing);
# 86 : 2 : BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in getheaders
# 87 : 2 : }
# 88 : 2 : {
# 89 : 2 : LOCK(dummyNode1.cs_vSend);
# 90 : 2 : BOOST_CHECK(dummyNode1.vSendMsg.size() > 0);
# 91 : 2 : dummyNode1.vSendMsg.clear();
# 92 : 2 : }
# 93 : :
# 94 : 2 : int64_t nStartTime = GetTime();
# 95 : : // Wait 21 minutes
# 96 : 2 : SetMockTime(nStartTime+21*60);
# 97 : 2 : {
# 98 : 2 : LOCK(dummyNode1.cs_sendProcessing);
# 99 : 2 : BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in getheaders
# 100 : 2 : }
# 101 : 2 : {
# 102 : 2 : LOCK(dummyNode1.cs_vSend);
# 103 : 2 : BOOST_CHECK(dummyNode1.vSendMsg.size() > 0);
# 104 : 2 : }
# 105 : : // Wait 3 more minutes
# 106 : 2 : SetMockTime(nStartTime+24*60);
# 107 : 2 : {
# 108 : 2 : LOCK(dummyNode1.cs_sendProcessing);
# 109 : 2 : BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in disconnect
# 110 : 2 : }
# 111 : 2 : BOOST_CHECK(dummyNode1.fDisconnect == true);
# 112 : :
# 113 : 2 : peerLogic->FinalizeNode(dummyNode1);
# 114 : 2 : }
# 115 : :
# 116 : : static void AddRandomOutboundPeer(NodeId& id, std::vector<CNode*>& vNodes, PeerManager& peerLogic, ConnmanTestMsg& connman, ConnectionType connType)
# 117 : 24 : {
# 118 : 24 : CAddress addr(ip(g_insecure_rand_ctx.randbits(32)), NODE_NONE);
# 119 : 24 : vNodes.emplace_back(new CNode{id++,
# 120 : 24 : ServiceFlags(NODE_NETWORK | NODE_WITNESS),
# 121 : 24 : /*sock=*/nullptr,
# 122 : 24 : addr,
# 123 : 24 : /*nKeyedNetGroupIn=*/0,
# 124 : 24 : /*nLocalHostNonceIn=*/0,
# 125 : 24 : CAddress(),
# 126 : 24 : /*addrNameIn=*/"",
# 127 : 24 : connType,
# 128 : 24 : /*inbound_onion=*/false});
# 129 : 24 : CNode &node = *vNodes.back();
# 130 : 24 : node.SetCommonVersion(PROTOCOL_VERSION);
# 131 : :
# 132 : 24 : peerLogic.InitializeNode(&node);
# 133 : 24 : node.fSuccessfullyConnected = true;
# 134 : :
# 135 : 24 : connman.AddTestNode(node);
# 136 : 24 : }
# 137 : :
# 138 : : BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
# 139 : 2 : {
# 140 : 2 : NodeId id{0};
# 141 : 2 : const CChainParams& chainparams = Params();
# 142 : 2 : auto connman = std::make_unique<ConnmanTestMsg>(0x1337, 0x1337, *m_node.addrman);
# 143 : 2 : auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr,
# 144 : 2 : *m_node.chainman, *m_node.mempool, false);
# 145 : :
# 146 : 2 : constexpr int max_outbound_full_relay = MAX_OUTBOUND_FULL_RELAY_CONNECTIONS;
# 147 : 2 : CConnman::Options options;
# 148 : 2 : options.nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS;
# 149 : 2 : options.m_max_outbound_full_relay = max_outbound_full_relay;
# 150 : 2 : options.nMaxFeeler = MAX_FEELER_CONNECTIONS;
# 151 : :
# 152 : 2 : const auto time_init{GetTime<std::chrono::seconds>()};
# 153 : 2 : SetMockTime(time_init);
# 154 : 2 : const auto time_later{time_init + 3 * std::chrono::seconds{chainparams.GetConsensus().nPowTargetSpacing} + 1s};
# 155 : 2 : connman->Init(options);
# 156 : 2 : std::vector<CNode *> vNodes;
# 157 : :
# 158 : : // Mock some outbound peers
# 159 [ + + ]: 18 : for (int i = 0; i < max_outbound_full_relay; ++i) {
# 160 : 16 : AddRandomOutboundPeer(id, vNodes, *peerLogic, *connman, ConnectionType::OUTBOUND_FULL_RELAY);
# 161 : 16 : }
# 162 : :
# 163 : 2 : peerLogic->CheckForStaleTipAndEvictPeers();
# 164 : :
# 165 : : // No nodes should be marked for disconnection while we have no extra peers
# 166 [ + + ]: 16 : for (const CNode *node : vNodes) {
# 167 : 16 : BOOST_CHECK(node->fDisconnect == false);
# 168 : 16 : }
# 169 : :
# 170 : 2 : SetMockTime(time_later);
# 171 : :
# 172 : : // Now tip should definitely be stale, and we should look for an extra
# 173 : : // outbound peer
# 174 : 2 : peerLogic->CheckForStaleTipAndEvictPeers();
# 175 : 2 : BOOST_CHECK(connman->GetTryNewOutboundPeer());
# 176 : :
# 177 : : // Still no peers should be marked for disconnection
# 178 [ + + ]: 16 : for (const CNode *node : vNodes) {
# 179 : 16 : BOOST_CHECK(node->fDisconnect == false);
# 180 : 16 : }
# 181 : :
# 182 : : // If we add one more peer, something should get marked for eviction
# 183 : : // on the next check (since we're mocking the time to be in the future, the
# 184 : : // required time connected check should be satisfied).
# 185 : 2 : SetMockTime(time_init);
# 186 : 2 : AddRandomOutboundPeer(id, vNodes, *peerLogic, *connman, ConnectionType::OUTBOUND_FULL_RELAY);
# 187 : 2 : SetMockTime(time_later);
# 188 : :
# 189 : 2 : peerLogic->CheckForStaleTipAndEvictPeers();
# 190 [ + + ]: 18 : for (int i = 0; i < max_outbound_full_relay; ++i) {
# 191 : 16 : BOOST_CHECK(vNodes[i]->fDisconnect == false);
# 192 : 16 : }
# 193 : : // Last added node should get marked for eviction
# 194 : 2 : BOOST_CHECK(vNodes.back()->fDisconnect == true);
# 195 : :
# 196 : 2 : vNodes.back()->fDisconnect = false;
# 197 : :
# 198 : : // Update the last announced block time for the last
# 199 : : // peer, and check that the next newest node gets evicted.
# 200 : 2 : UpdateLastBlockAnnounceTime(vNodes.back()->GetId(), GetTime());
# 201 : :
# 202 : 2 : peerLogic->CheckForStaleTipAndEvictPeers();
# 203 [ + + ]: 16 : for (int i = 0; i < max_outbound_full_relay - 1; ++i) {
# 204 : 14 : BOOST_CHECK(vNodes[i]->fDisconnect == false);
# 205 : 14 : }
# 206 : 2 : BOOST_CHECK(vNodes[max_outbound_full_relay-1]->fDisconnect == true);
# 207 : 2 : BOOST_CHECK(vNodes.back()->fDisconnect == false);
# 208 : :
# 209 [ + + ]: 18 : for (const CNode *node : vNodes) {
# 210 : 18 : peerLogic->FinalizeNode(*node);
# 211 : 18 : }
# 212 : :
# 213 : 2 : connman->ClearTestNodes();
# 214 : 2 : }
# 215 : :
# 216 : : BOOST_AUTO_TEST_CASE(block_relay_only_eviction)
# 217 : 2 : {
# 218 : 2 : NodeId id{0};
# 219 : 2 : const CChainParams& chainparams = Params();
# 220 : 2 : auto connman = std::make_unique<ConnmanTestMsg>(0x1337, 0x1337, *m_node.addrman);
# 221 : 2 : auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr,
# 222 : 2 : *m_node.chainman, *m_node.mempool, false);
# 223 : :
# 224 : 2 : constexpr int max_outbound_block_relay{MAX_BLOCK_RELAY_ONLY_CONNECTIONS};
# 225 : 2 : constexpr int64_t MINIMUM_CONNECT_TIME{30};
# 226 : 2 : CConnman::Options options;
# 227 : 2 : options.nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS;
# 228 : 2 : options.m_max_outbound_full_relay = MAX_OUTBOUND_FULL_RELAY_CONNECTIONS;
# 229 : 2 : options.m_max_outbound_block_relay = max_outbound_block_relay;
# 230 : :
# 231 : 2 : connman->Init(options);
# 232 : 2 : std::vector<CNode*> vNodes;
# 233 : :
# 234 : : // Add block-relay-only peers up to the limit
# 235 [ + + ]: 6 : for (int i = 0; i < max_outbound_block_relay; ++i) {
# 236 : 4 : AddRandomOutboundPeer(id, vNodes, *peerLogic, *connman, ConnectionType::BLOCK_RELAY);
# 237 : 4 : }
# 238 : 2 : peerLogic->CheckForStaleTipAndEvictPeers();
# 239 : :
# 240 [ + + ]: 6 : for (int i = 0; i < max_outbound_block_relay; ++i) {
# 241 : 4 : BOOST_CHECK(vNodes[i]->fDisconnect == false);
# 242 : 4 : }
# 243 : :
# 244 : : // Add an extra block-relay-only peer breaking the limit (mocks logic in ThreadOpenConnections)
# 245 : 2 : AddRandomOutboundPeer(id, vNodes, *peerLogic, *connman, ConnectionType::BLOCK_RELAY);
# 246 : 2 : peerLogic->CheckForStaleTipAndEvictPeers();
# 247 : :
# 248 : : // The extra peer should only get marked for eviction after MINIMUM_CONNECT_TIME
# 249 [ + + ]: 6 : for (int i = 0; i < max_outbound_block_relay; ++i) {
# 250 : 4 : BOOST_CHECK(vNodes[i]->fDisconnect == false);
# 251 : 4 : }
# 252 : 2 : BOOST_CHECK(vNodes.back()->fDisconnect == false);
# 253 : :
# 254 : 2 : SetMockTime(GetTime() + MINIMUM_CONNECT_TIME + 1);
# 255 : 2 : peerLogic->CheckForStaleTipAndEvictPeers();
# 256 [ + + ]: 6 : for (int i = 0; i < max_outbound_block_relay; ++i) {
# 257 : 4 : BOOST_CHECK(vNodes[i]->fDisconnect == false);
# 258 : 4 : }
# 259 : 2 : BOOST_CHECK(vNodes.back()->fDisconnect == true);
# 260 : :
# 261 : : // Update the last block time for the extra peer,
# 262 : : // and check that the next youngest peer gets evicted.
# 263 : 2 : vNodes.back()->fDisconnect = false;
# 264 : 2 : vNodes.back()->m_last_block_time = GetTime<std::chrono::seconds>();
# 265 : :
# 266 : 2 : peerLogic->CheckForStaleTipAndEvictPeers();
# 267 [ + + ]: 4 : for (int i = 0; i < max_outbound_block_relay - 1; ++i) {
# 268 : 2 : BOOST_CHECK(vNodes[i]->fDisconnect == false);
# 269 : 2 : }
# 270 : 2 : BOOST_CHECK(vNodes[max_outbound_block_relay - 1]->fDisconnect == true);
# 271 : 2 : BOOST_CHECK(vNodes.back()->fDisconnect == false);
# 272 : :
# 273 [ + + ]: 6 : for (const CNode* node : vNodes) {
# 274 : 6 : peerLogic->FinalizeNode(*node);
# 275 : 6 : }
# 276 : 2 : connman->ClearTestNodes();
# 277 : 2 : }
# 278 : :
# 279 : : BOOST_AUTO_TEST_CASE(peer_discouragement)
# 280 : 2 : {
# 281 : 2 : const CChainParams& chainparams = Params();
# 282 : 2 : auto banman = std::make_unique<BanMan>(m_args.GetDataDirBase() / "banlist", nullptr, DEFAULT_MISBEHAVING_BANTIME);
# 283 : 2 : auto connman = std::make_unique<ConnmanTestMsg>(0x1337, 0x1337, *m_node.addrman);
# 284 : 2 : auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(),
# 285 : 2 : *m_node.chainman, *m_node.mempool, false);
# 286 : :
# 287 : 2 : CNetAddr tor_netaddr;
# 288 : 2 : BOOST_REQUIRE(
# 289 : 2 : tor_netaddr.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion"));
# 290 : 2 : const CService tor_service{tor_netaddr, Params().GetDefaultPort()};
# 291 : :
# 292 : 2 : const std::array<CAddress, 3> addr{CAddress{ip(0xa0b0c001), NODE_NONE},
# 293 : 2 : CAddress{ip(0xa0b0c002), NODE_NONE},
# 294 : 2 : CAddress{tor_service, NODE_NONE}};
# 295 : :
# 296 : 2 : const CNetAddr other_addr{ip(0xa0b0ff01)}; // Not any of addr[].
# 297 : :
# 298 : 2 : std::array<CNode*, 3> nodes;
# 299 : :
# 300 : 2 : banman->ClearBanned();
# 301 : 2 : NodeId id{0};
# 302 : 2 : nodes[0] = new CNode{id++,
# 303 : 2 : NODE_NETWORK,
# 304 : 2 : /*sock=*/nullptr,
# 305 : 2 : addr[0],
# 306 : 2 : /*nKeyedNetGroupIn=*/0,
# 307 : 2 : /*nLocalHostNonceIn=*/0,
# 308 : 2 : CAddress(),
# 309 : 2 : /*addrNameIn=*/"",
# 310 : 2 : ConnectionType::INBOUND,
# 311 : 2 : /*inbound_onion=*/false};
# 312 : 2 : nodes[0]->SetCommonVersion(PROTOCOL_VERSION);
# 313 : 2 : peerLogic->InitializeNode(nodes[0]);
# 314 : 2 : nodes[0]->fSuccessfullyConnected = true;
# 315 : 2 : connman->AddTestNode(*nodes[0]);
# 316 : 2 : peerLogic->Misbehaving(nodes[0]->GetId(), DISCOURAGEMENT_THRESHOLD, /*message=*/""); // Should be discouraged
# 317 : 2 : {
# 318 : 2 : LOCK(nodes[0]->cs_sendProcessing);
# 319 : 2 : BOOST_CHECK(peerLogic->SendMessages(nodes[0]));
# 320 : 2 : }
# 321 : 2 : BOOST_CHECK(banman->IsDiscouraged(addr[0]));
# 322 : 2 : BOOST_CHECK(nodes[0]->fDisconnect);
# 323 : 2 : BOOST_CHECK(!banman->IsDiscouraged(other_addr)); // Different address, not discouraged
# 324 : :
# 325 : 2 : nodes[1] = new CNode{id++,
# 326 : 2 : NODE_NETWORK,
# 327 : 2 : /*sock=*/nullptr,
# 328 : 2 : addr[1],
# 329 : 2 : /*nKeyedNetGroupIn=*/1,
# 330 : 2 : /*nLocalHostNonceIn=*/1,
# 331 : 2 : CAddress(),
# 332 : 2 : /*addrNameIn=*/"",
# 333 : 2 : ConnectionType::INBOUND,
# 334 : 2 : /*inbound_onion=*/false};
# 335 : 2 : nodes[1]->SetCommonVersion(PROTOCOL_VERSION);
# 336 : 2 : peerLogic->InitializeNode(nodes[1]);
# 337 : 2 : nodes[1]->fSuccessfullyConnected = true;
# 338 : 2 : connman->AddTestNode(*nodes[1]);
# 339 : 2 : peerLogic->Misbehaving(nodes[1]->GetId(), DISCOURAGEMENT_THRESHOLD - 1, /*message=*/"");
# 340 : 2 : {
# 341 : 2 : LOCK(nodes[1]->cs_sendProcessing);
# 342 : 2 : BOOST_CHECK(peerLogic->SendMessages(nodes[1]));
# 343 : 2 : }
# 344 : : // [0] is still discouraged/disconnected.
# 345 : 2 : BOOST_CHECK(banman->IsDiscouraged(addr[0]));
# 346 : 2 : BOOST_CHECK(nodes[0]->fDisconnect);
# 347 : : // [1] is not discouraged/disconnected yet.
# 348 : 2 : BOOST_CHECK(!banman->IsDiscouraged(addr[1]));
# 349 : 2 : BOOST_CHECK(!nodes[1]->fDisconnect);
# 350 : 2 : peerLogic->Misbehaving(nodes[1]->GetId(), 1, /*message=*/""); // [1] reaches discouragement threshold
# 351 : 2 : {
# 352 : 2 : LOCK(nodes[1]->cs_sendProcessing);
# 353 : 2 : BOOST_CHECK(peerLogic->SendMessages(nodes[1]));
# 354 : 2 : }
# 355 : : // Expect both [0] and [1] to be discouraged/disconnected now.
# 356 : 2 : BOOST_CHECK(banman->IsDiscouraged(addr[0]));
# 357 : 2 : BOOST_CHECK(nodes[0]->fDisconnect);
# 358 : 2 : BOOST_CHECK(banman->IsDiscouraged(addr[1]));
# 359 : 2 : BOOST_CHECK(nodes[1]->fDisconnect);
# 360 : :
# 361 : : // Make sure non-IP peers are discouraged and disconnected properly.
# 362 : :
# 363 : 2 : nodes[2] = new CNode{id++,
# 364 : 2 : NODE_NETWORK,
# 365 : 2 : /*sock=*/nullptr,
# 366 : 2 : addr[2],
# 367 : 2 : /*nKeyedNetGroupIn=*/1,
# 368 : 2 : /*nLocalHostNonceIn=*/1,
# 369 : 2 : CAddress(),
# 370 : 2 : /*addrNameIn=*/"",
# 371 : 2 : ConnectionType::OUTBOUND_FULL_RELAY,
# 372 : 2 : /*inbound_onion=*/false};
# 373 : 2 : nodes[2]->SetCommonVersion(PROTOCOL_VERSION);
# 374 : 2 : peerLogic->InitializeNode(nodes[2]);
# 375 : 2 : nodes[2]->fSuccessfullyConnected = true;
# 376 : 2 : connman->AddTestNode(*nodes[2]);
# 377 : 2 : peerLogic->Misbehaving(nodes[2]->GetId(), DISCOURAGEMENT_THRESHOLD, /*message=*/"");
# 378 : 2 : {
# 379 : 2 : LOCK(nodes[2]->cs_sendProcessing);
# 380 : 2 : BOOST_CHECK(peerLogic->SendMessages(nodes[2]));
# 381 : 2 : }
# 382 : 2 : BOOST_CHECK(banman->IsDiscouraged(addr[0]));
# 383 : 2 : BOOST_CHECK(banman->IsDiscouraged(addr[1]));
# 384 : 2 : BOOST_CHECK(banman->IsDiscouraged(addr[2]));
# 385 : 2 : BOOST_CHECK(nodes[0]->fDisconnect);
# 386 : 2 : BOOST_CHECK(nodes[1]->fDisconnect);
# 387 : 2 : BOOST_CHECK(nodes[2]->fDisconnect);
# 388 : :
# 389 [ + + ]: 6 : for (CNode* node : nodes) {
# 390 : 6 : peerLogic->FinalizeNode(*node);
# 391 : 6 : }
# 392 : 2 : connman->ClearTestNodes();
# 393 : 2 : }
# 394 : :
# 395 : : BOOST_AUTO_TEST_CASE(DoS_bantime)
# 396 : 2 : {
# 397 : 2 : const CChainParams& chainparams = Params();
# 398 : 2 : auto banman = std::make_unique<BanMan>(m_args.GetDataDirBase() / "banlist", nullptr, DEFAULT_MISBEHAVING_BANTIME);
# 399 : 2 : auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
# 400 : 2 : auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(),
# 401 : 2 : *m_node.chainman, *m_node.mempool, false);
# 402 : :
# 403 : 2 : banman->ClearBanned();
# 404 : 2 : int64_t nStartTime = GetTime();
# 405 : 2 : SetMockTime(nStartTime); // Overrides future calls to GetTime()
# 406 : :
# 407 : 2 : CAddress addr(ip(0xa0b0c001), NODE_NONE);
# 408 : 2 : NodeId id{0};
# 409 : 2 : CNode dummyNode{id++,
# 410 : 2 : NODE_NETWORK,
# 411 : 2 : /*sock=*/nullptr,
# 412 : 2 : addr,
# 413 : 2 : /*nKeyedNetGroupIn=*/4,
# 414 : 2 : /*nLocalHostNonceIn=*/4,
# 415 : 2 : CAddress(),
# 416 : 2 : /*addrNameIn=*/"",
# 417 : 2 : ConnectionType::INBOUND,
# 418 : 2 : /*inbound_onion=*/false};
# 419 : 2 : dummyNode.SetCommonVersion(PROTOCOL_VERSION);
# 420 : 2 : peerLogic->InitializeNode(&dummyNode);
# 421 : 2 : dummyNode.fSuccessfullyConnected = true;
# 422 : :
# 423 : 2 : peerLogic->Misbehaving(dummyNode.GetId(), DISCOURAGEMENT_THRESHOLD, /*message=*/"");
# 424 : 2 : {
# 425 : 2 : LOCK(dummyNode.cs_sendProcessing);
# 426 : 2 : BOOST_CHECK(peerLogic->SendMessages(&dummyNode));
# 427 : 2 : }
# 428 : 2 : BOOST_CHECK(banman->IsDiscouraged(addr));
# 429 : :
# 430 : 2 : peerLogic->FinalizeNode(dummyNode);
# 431 : 2 : }
# 432 : :
# 433 : : class TxOrphanageTest : public TxOrphanage
# 434 : : {
# 435 : : public:
# 436 : : inline size_t CountOrphans() const EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
# 437 : 18 : {
# 438 : 18 : return m_orphans.size();
# 439 : 18 : }
# 440 : :
# 441 : : CTransactionRef RandomOrphan() EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
# 442 : 120 : {
# 443 : 120 : std::map<uint256, OrphanTx>::iterator it;
# 444 : 120 : it = m_orphans.lower_bound(InsecureRand256());
# 445 [ - + ]: 120 : if (it == m_orphans.end())
# 446 : 0 : it = m_orphans.begin();
# 447 : 120 : return it->second.tx;
# 448 : 120 : }
# 449 : : };
# 450 : :
# 451 : : static void MakeNewKeyWithFastRandomContext(CKey& key)
# 452 : 2 : {
# 453 : 2 : std::vector<unsigned char> keydata;
# 454 : 2 : keydata = g_insecure_rand_ctx.randbytes(32);
# 455 : 2 : key.Set(keydata.data(), keydata.data() + keydata.size(), /*fCompressedIn=*/true);
# 456 : 2 : assert(key.IsValid());
# 457 : 2 : }
# 458 : :
# 459 : : BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
# 460 : 2 : {
# 461 : : // This test had non-deterministic coverage due to
# 462 : : // randomly selected seeds.
# 463 : : // This seed is chosen so that all branches of the function
# 464 : : // ecdsa_signature_parse_der_lax are executed during this test.
# 465 : : // Specifically branches that run only when an ECDSA
# 466 : : // signature's R and S values have leading zeros.
# 467 : 2 : g_insecure_rand_ctx = FastRandomContext(ArithToUint256(arith_uint256(33)));
# 468 : :
# 469 : 2 : TxOrphanageTest orphanage;
# 470 : 2 : CKey key;
# 471 : 2 : MakeNewKeyWithFastRandomContext(key);
# 472 : 2 : FillableSigningProvider keystore;
# 473 : 2 : BOOST_CHECK(keystore.AddKey(key));
# 474 : :
# 475 : 2 : LOCK(g_cs_orphans);
# 476 : :
# 477 : : // 50 orphan transactions:
# 478 [ + + ]: 102 : for (int i = 0; i < 50; i++)
# 479 : 100 : {
# 480 : 100 : CMutableTransaction tx;
# 481 : 100 : tx.vin.resize(1);
# 482 : 100 : tx.vin[0].prevout.n = 0;
# 483 : 100 : tx.vin[0].prevout.hash = InsecureRand256();
# 484 : 100 : tx.vin[0].scriptSig << OP_1;
# 485 : 100 : tx.vout.resize(1);
# 486 : 100 : tx.vout[0].nValue = 1*CENT;
# 487 : 100 : tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
# 488 : :
# 489 : 100 : orphanage.AddTx(MakeTransactionRef(tx), i);
# 490 : 100 : }
# 491 : :
# 492 : : // ... and 50 that depend on other orphans:
# 493 [ + + ]: 102 : for (int i = 0; i < 50; i++)
# 494 : 100 : {
# 495 : 100 : CTransactionRef txPrev = orphanage.RandomOrphan();
# 496 : :
# 497 : 100 : CMutableTransaction tx;
# 498 : 100 : tx.vin.resize(1);
# 499 : 100 : tx.vin[0].prevout.n = 0;
# 500 : 100 : tx.vin[0].prevout.hash = txPrev->GetHash();
# 501 : 100 : tx.vout.resize(1);
# 502 : 100 : tx.vout[0].nValue = 1*CENT;
# 503 : 100 : tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
# 504 : 100 : BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL));
# 505 : :
# 506 : 100 : orphanage.AddTx(MakeTransactionRef(tx), i);
# 507 : 100 : }
# 508 : :
# 509 : : // This really-big orphan should be ignored:
# 510 [ + + ]: 22 : for (int i = 0; i < 10; i++)
# 511 : 20 : {
# 512 : 20 : CTransactionRef txPrev = orphanage.RandomOrphan();
# 513 : :
# 514 : 20 : CMutableTransaction tx;
# 515 : 20 : tx.vout.resize(1);
# 516 : 20 : tx.vout[0].nValue = 1*CENT;
# 517 : 20 : tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
# 518 : 20 : tx.vin.resize(2777);
# 519 [ + + ]: 55560 : for (unsigned int j = 0; j < tx.vin.size(); j++)
# 520 : 55540 : {
# 521 : 55540 : tx.vin[j].prevout.n = j;
# 522 : 55540 : tx.vin[j].prevout.hash = txPrev->GetHash();
# 523 : 55540 : }
# 524 : 20 : BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL));
# 525 : : // Re-use same signature for other inputs
# 526 : : // (they don't have to be valid for this test)
# 527 [ + + ]: 55540 : for (unsigned int j = 1; j < tx.vin.size(); j++)
# 528 : 55520 : tx.vin[j].scriptSig = tx.vin[0].scriptSig;
# 529 : :
# 530 : 20 : BOOST_CHECK(!orphanage.AddTx(MakeTransactionRef(tx), i));
# 531 : 20 : }
# 532 : :
# 533 : : // Test EraseOrphansFor:
# 534 [ + + ]: 8 : for (NodeId i = 0; i < 3; i++)
# 535 : 6 : {
# 536 : 6 : size_t sizeBefore = orphanage.CountOrphans();
# 537 : 6 : orphanage.EraseForPeer(i);
# 538 : 6 : BOOST_CHECK(orphanage.CountOrphans() < sizeBefore);
# 539 : 6 : }
# 540 : :
# 541 : : // Test LimitOrphanTxSize() function:
# 542 : 2 : orphanage.LimitOrphans(40);
# 543 : 2 : BOOST_CHECK(orphanage.CountOrphans() <= 40);
# 544 : 2 : orphanage.LimitOrphans(10);
# 545 : 2 : BOOST_CHECK(orphanage.CountOrphans() <= 10);
# 546 : 2 : orphanage.LimitOrphans(0);
# 547 : 2 : BOOST_CHECK(orphanage.CountOrphans() == 0);
# 548 : 2 : }
# 549 : :
# 550 : : BOOST_AUTO_TEST_SUITE_END()
|