LCOV - code coverage report
Current view: top level - src/test - denialofservice_tests.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 384 385 99.7 %
Date: 2022-04-21 14:51:19 Functions: 11 11 100.0 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 39 40 97.5 %

           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()

Generated by: LCOV version 0-eol-96201-ge66f56f4af6a