LCOV - code coverage report
Current view: top level - src/test - DoS_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 113 113 100.0 %
Date: 2015-10-12 22:39:14 Functions: 12 20 60.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2011-2014 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 "chainparams.h"
       8             : #include "keystore.h"
       9             : #include "main.h"
      10             : #include "net.h"
      11             : #include "pow.h"
      12             : #include "script/sign.h"
      13             : #include "serialize.h"
      14             : #include "util.h"
      15             : 
      16             : #include "test/test_bitcoin.h"
      17             : 
      18             : #include <stdint.h>
      19             : 
      20             : #include <boost/assign/list_of.hpp> // for 'map_list_of()'
      21             : #include <boost/date_time/posix_time/posix_time_types.hpp>
      22             : #include <boost/foreach.hpp>
      23             : #include <boost/test/unit_test.hpp>
      24             : 
      25             : // Tests this internal-to-main.cpp method:
      26             : extern bool AddOrphanTx(const CTransaction& tx, NodeId peer);
      27             : extern void EraseOrphansFor(NodeId peer);
      28             : extern unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans);
      29             : struct COrphanTx {
      30             :     CTransaction tx;
      31             :     NodeId fromPeer;
      32             : };
      33             : extern std::map<uint256, COrphanTx> mapOrphanTransactions;
      34             : extern std::map<uint256, std::set<uint256> > mapOrphanTransactionsByPrev;
      35             : 
      36           5 : CService ip(uint32_t i)
      37             : {
      38             :     struct in_addr s;
      39           5 :     s.s_addr = i;
      40           5 :     return CService(CNetAddr(s), Params().GetDefaultPort());
      41             : }
      42             : 
      43           1 : BOOST_FIXTURE_TEST_SUITE(DoS_tests, TestingSetup)
      44             : 
      45           6 : BOOST_AUTO_TEST_CASE(DoS_banning)
      46             : {
      47           1 :     CNode::ClearBanned();
      48           1 :     CAddress addr1(ip(0xa0b0c001));
      49           3 :     CNode dummyNode1(INVALID_SOCKET, addr1, "", true);
      50           1 :     dummyNode1.nVersion = 1;
      51           1 :     Misbehaving(dummyNode1.GetId(), 100); // Should get banned
      52           1 :     SendMessages(&dummyNode1, false);
      53           8 :     BOOST_CHECK(CNode::IsBanned(addr1));
      54           8 :     BOOST_CHECK(!CNode::IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned
      55             : 
      56           1 :     CAddress addr2(ip(0xa0b0c002));
      57           4 :     CNode dummyNode2(INVALID_SOCKET, addr2, "", true);
      58           1 :     dummyNode2.nVersion = 1;
      59           1 :     Misbehaving(dummyNode2.GetId(), 50);
      60           1 :     SendMessages(&dummyNode2, false);
      61           8 :     BOOST_CHECK(!CNode::IsBanned(addr2)); // 2 not banned yet...
      62           8 :     BOOST_CHECK(CNode::IsBanned(addr1));  // ... but 1 still should be
      63           1 :     Misbehaving(dummyNode2.GetId(), 50);
      64           1 :     SendMessages(&dummyNode2, false);
      65           9 :     BOOST_CHECK(CNode::IsBanned(addr2));
      66           1 : }
      67             : 
      68           6 : BOOST_AUTO_TEST_CASE(DoS_banscore)
      69             : {
      70           1 :     CNode::ClearBanned();
      71           3 :     mapArgs["-banscore"] = "111"; // because 11 is my favorite number
      72           1 :     CAddress addr1(ip(0xa0b0c001));
      73           3 :     CNode dummyNode1(INVALID_SOCKET, addr1, "", true);
      74           1 :     dummyNode1.nVersion = 1;
      75           1 :     Misbehaving(dummyNode1.GetId(), 100);
      76           1 :     SendMessages(&dummyNode1, false);
      77           8 :     BOOST_CHECK(!CNode::IsBanned(addr1));
      78           1 :     Misbehaving(dummyNode1.GetId(), 10);
      79           1 :     SendMessages(&dummyNode1, false);
      80           8 :     BOOST_CHECK(!CNode::IsBanned(addr1));
      81           1 :     Misbehaving(dummyNode1.GetId(), 1);
      82           1 :     SendMessages(&dummyNode1, false);
      83           8 :     BOOST_CHECK(CNode::IsBanned(addr1));
      84           3 :     mapArgs.erase("-banscore");
      85           1 : }
      86             : 
      87           6 : BOOST_AUTO_TEST_CASE(DoS_bantime)
      88             : {
      89           1 :     CNode::ClearBanned();
      90           1 :     int64_t nStartTime = GetTime();
      91           1 :     SetMockTime(nStartTime); // Overrides future calls to GetTime()
      92             : 
      93           1 :     CAddress addr(ip(0xa0b0c001));
      94           3 :     CNode dummyNode(INVALID_SOCKET, addr, "", true);
      95           1 :     dummyNode.nVersion = 1;
      96             : 
      97           1 :     Misbehaving(dummyNode.GetId(), 100);
      98           1 :     SendMessages(&dummyNode, false);
      99           8 :     BOOST_CHECK(CNode::IsBanned(addr));
     100             : 
     101           1 :     SetMockTime(nStartTime+60*60);
     102           8 :     BOOST_CHECK(CNode::IsBanned(addr));
     103             : 
     104           1 :     SetMockTime(nStartTime+60*60*24+1);
     105           8 :     BOOST_CHECK(!CNode::IsBanned(addr));
     106           1 : }
     107             : 
     108          60 : CTransaction RandomOrphan()
     109             : {
     110             :     std::map<uint256, COrphanTx>::iterator it;
     111         120 :     it = mapOrphanTransactions.lower_bound(GetRandHash());
     112          60 :     if (it == mapOrphanTransactions.end())
     113           1 :         it = mapOrphanTransactions.begin();
     114          60 :     return it->second.tx;
     115             : }
     116             : 
     117           6 : BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
     118             : {
     119             :     CKey key;
     120           1 :     key.MakeNewKey(true);
     121           2 :     CBasicKeyStore keystore;
     122           1 :     keystore.AddKey(key);
     123             : 
     124             :     // 50 orphan transactions:
     125          50 :     for (int i = 0; i < 50; i++)
     126             :     {
     127          50 :         CMutableTransaction tx;
     128         100 :         tx.vin.resize(1);
     129          50 :         tx.vin[0].prevout.n = 0;
     130          50 :         tx.vin[0].prevout.hash = GetRandHash();
     131          50 :         tx.vin[0].scriptSig << OP_1;
     132         100 :         tx.vout.resize(1);
     133          50 :         tx.vout[0].nValue = 1*CENT;
     134         200 :         tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
     135             : 
     136         100 :         AddOrphanTx(tx, i);
     137             :     }
     138             : 
     139             :     // ... and 50 that depend on other orphans:
     140          50 :     for (int i = 0; i < 50; i++)
     141             :     {
     142          50 :         CTransaction txPrev = RandomOrphan();
     143             : 
     144          50 :         CMutableTransaction tx;
     145         100 :         tx.vin.resize(1);
     146          50 :         tx.vin[0].prevout.n = 0;
     147          50 :         tx.vin[0].prevout.hash = txPrev.GetHash();
     148         100 :         tx.vout.resize(1);
     149          50 :         tx.vout[0].nValue = 1*CENT;
     150         200 :         tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
     151          50 :         SignSignature(keystore, txPrev, tx, 0);
     152             : 
     153         100 :         AddOrphanTx(tx, i);
     154             :     }
     155             : 
     156             :     // This really-big orphan should be ignored:
     157          10 :     for (int i = 0; i < 10; i++)
     158             :     {
     159          10 :         CTransaction txPrev = RandomOrphan();
     160             : 
     161          10 :         CMutableTransaction tx;
     162          20 :         tx.vout.resize(1);
     163          10 :         tx.vout[0].nValue = 1*CENT;
     164          40 :         tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
     165          20 :         tx.vin.resize(500);
     166       10020 :         for (unsigned int j = 0; j < tx.vin.size(); j++)
     167             :         {
     168       10000 :             tx.vin[j].prevout.n = j;
     169        5000 :             tx.vin[j].prevout.hash = txPrev.GetHash();
     170             :         }
     171          10 :         SignSignature(keystore, txPrev, tx, 0);
     172             :         // Re-use same signature for other inputs
     173             :         // (they don't have to be valid for this test)
     174        9990 :         for (unsigned int j = 1; j < tx.vin.size(); j++)
     175        9980 :             tx.vin[j].scriptSig = tx.vin[0].scriptSig;
     176             : 
     177          90 :         BOOST_CHECK(!AddOrphanTx(tx, i));
     178             :     }
     179             : 
     180             :     // Test EraseOrphansFor:
     181           3 :     for (NodeId i = 0; i < 3; i++)
     182             :     {
     183           3 :         size_t sizeBefore = mapOrphanTransactions.size();
     184           3 :         EraseOrphansFor(i);
     185          24 :         BOOST_CHECK(mapOrphanTransactions.size() < sizeBefore);
     186             :     }
     187             : 
     188             :     // Test LimitOrphanTxSize() function:
     189           1 :     LimitOrphanTxSize(40);
     190           8 :     BOOST_CHECK(mapOrphanTransactions.size() <= 40);
     191           1 :     LimitOrphanTxSize(10);
     192           8 :     BOOST_CHECK(mapOrphanTransactions.size() <= 10);
     193           1 :     LimitOrphanTxSize(0);
     194           8 :     BOOST_CHECK(mapOrphanTransactions.empty());
     195           8 :     BOOST_CHECK(mapOrphanTransactionsByPrev.empty());
     196           1 : }
     197             : 
     198           3 : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.11