raw
genesis                 1 //
genesis 2 // Unit tests for denial-of-service detection/prevention code
genesis 3 //
genesis 4 #include <boost/assign/list_of.hpp> // for 'map_list_of()'
genesis 5 #include <boost/test/unit_test.hpp>
genesis 6 #include <boost/foreach.hpp>
genesis 7
genesis 8 #include "../main.h"
genesis 9 #include "../net.h"
genesis 10 #include "../util.h"
genesis 11
genesis 12 using namespace std;
genesis 13
genesis 14 BOOST_AUTO_TEST_SUITE(DoS_tests)
genesis 15
genesis 16 BOOST_AUTO_TEST_CASE(DoS_banning)
genesis 17 {
genesis 18 CNode::ClearBanned();
genesis 19 CAddress addr1(0xa0b0c001);
genesis 20 CNode dummyNode1(INVALID_SOCKET, addr1, true);
genesis 21 dummyNode1.Misbehaving(100); // Should get banned
genesis 22 BOOST_CHECK(CNode::IsBanned(addr1.ip));
genesis 23 BOOST_CHECK(!CNode::IsBanned(addr1.ip|0x0000ff00)); // Different ip, not banned
genesis 24
genesis 25 CAddress addr2(0xa0b0c002);
genesis 26 CNode dummyNode2(INVALID_SOCKET, addr2, true);
genesis 27 dummyNode2.Misbehaving(50);
genesis 28 BOOST_CHECK(!CNode::IsBanned(addr2.ip)); // 2 not banned yet...
genesis 29 BOOST_CHECK(CNode::IsBanned(addr1.ip)); // ... but 1 still should be
genesis 30 dummyNode2.Misbehaving(50);
genesis 31 BOOST_CHECK(CNode::IsBanned(addr2.ip));
genesis 32 }
genesis 33
genesis 34 BOOST_AUTO_TEST_CASE(DoS_banscore)
genesis 35 {
genesis 36 CNode::ClearBanned();
genesis 37 mapArgs["-banscore"] = "111"; // because 11 is my favorite number
genesis 38 CAddress addr1(0xa0b0c001);
genesis 39 CNode dummyNode1(INVALID_SOCKET, addr1, true);
genesis 40 dummyNode1.Misbehaving(100);
genesis 41 BOOST_CHECK(!CNode::IsBanned(addr1.ip));
genesis 42 dummyNode1.Misbehaving(10);
genesis 43 BOOST_CHECK(!CNode::IsBanned(addr1.ip));
genesis 44 dummyNode1.Misbehaving(1);
genesis 45 BOOST_CHECK(CNode::IsBanned(addr1.ip));
genesis 46 mapArgs["-banscore"] = "100";
genesis 47 }
genesis 48
genesis 49 BOOST_AUTO_TEST_CASE(DoS_bantime)
genesis 50 {
genesis 51 CNode::ClearBanned();
genesis 52 int64 nStartTime = GetTime();
genesis 53 SetMockTime(nStartTime); // Overrides future calls to GetTime()
genesis 54
genesis 55 CAddress addr(0xa0b0c001);
genesis 56 CNode dummyNode(INVALID_SOCKET, addr, true);
genesis 57
genesis 58 dummyNode.Misbehaving(100);
genesis 59 BOOST_CHECK(CNode::IsBanned(addr.ip));
genesis 60
genesis 61 SetMockTime(nStartTime+60*60);
genesis 62 BOOST_CHECK(CNode::IsBanned(addr.ip));
genesis 63
genesis 64 SetMockTime(nStartTime+60*60*24+1);
genesis 65 BOOST_CHECK(!CNode::IsBanned(addr.ip));
genesis 66 }
genesis 67
genesis 68 static bool CheckNBits(unsigned int nbits1, int64 time1, unsigned int nbits2, int64 time2)
genesis 69 {
genesis 70 if (time1 > time2)
genesis 71 return CheckNBits(nbits2, time2, nbits1, time1);
genesis 72 int64 deltaTime = time2-time1;
genesis 73
genesis 74 CBigNum required;
genesis 75 required.SetCompact(ComputeMinWork(nbits1, deltaTime));
genesis 76 CBigNum have;
genesis 77 have.SetCompact(nbits2);
genesis 78 return (have <= required);
genesis 79 }
genesis 80
genesis 81 BOOST_AUTO_TEST_CASE(DoS_checknbits)
genesis 82 {
genesis 83 using namespace boost::assign; // for 'map_list_of()'
genesis 84
genesis 85 // Timestamps,nBits from the bitcoin blockchain.
genesis 86 // These are the block-chain checkpoint blocks
genesis 87 typedef std::map<int64, unsigned int> BlockData;
genesis 88 BlockData chainData =
genesis 89 map_list_of(1239852051,486604799)(1262749024,486594666)
genesis 90 (1279305360,469854461)(1280200847,469830746)(1281678674,469809688)
genesis 91 (1296207707,453179945)(1302624061,453036989)(1309640330,437004818)
genesis 92 (1313172719,436789733);
genesis 93
genesis 94 // Make sure CheckNBits considers every combination of block-chain-lock-in-points
genesis 95 // "sane":
genesis 96 BOOST_FOREACH(const BlockData::value_type& i, chainData)
genesis 97 {
genesis 98 BOOST_FOREACH(const BlockData::value_type& j, chainData)
genesis 99 {
genesis 100 BOOST_CHECK(CheckNBits(i.second, i.first, j.second, j.first));
genesis 101 }
genesis 102 }
genesis 103
genesis 104 // Test a couple of insane combinations:
genesis 105 BlockData::value_type firstcheck = *(chainData.begin());
genesis 106 BlockData::value_type lastcheck = *(chainData.rbegin());
genesis 107
genesis 108 // First checkpoint difficulty at or a while after the last checkpoint time should fail when
genesis 109 // compared to last checkpoint
genesis 110 BOOST_CHECK(!CheckNBits(firstcheck.second, lastcheck.first+60*10, lastcheck.second, lastcheck.first));
genesis 111 BOOST_CHECK(!CheckNBits(firstcheck.second, lastcheck.first+60*60*24*14, lastcheck.second, lastcheck.first));
genesis 112
genesis 113 // ... but OK if enough time passed for difficulty to adjust downward:
genesis 114 BOOST_CHECK(CheckNBits(firstcheck.second, lastcheck.first+60*60*24*365*4, lastcheck.second, lastcheck.first));
genesis 115
genesis 116 }
genesis 117
genesis 118 BOOST_AUTO_TEST_SUITE_END()