1 // Copyright (c) 2011-2016 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.
5 // Unit tests for denial-of-service detection/prevention code
7 #include "chainparams.h"
10 #include "net_processing.h"
12 #include "script/sign.h"
13 #include "serialize.h"
15 #include "validation.h"
17 #include "test/test_bitcoin.h"
21 #include <boost/assign/list_of.hpp> // for 'map_list_of()'
22 #include <boost/date_time/posix_time/posix_time_types.hpp>
23 #include <boost/foreach.hpp>
24 #include <boost/test/unit_test.hpp>
26 // Tests these internal-to-net_processing.cpp methods:
27 extern bool AddOrphanTx(const CTransactionRef
& tx
, NodeId peer
);
28 extern void EraseOrphansFor(NodeId peer
);
29 extern unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans
);
35 extern std::map
<uint256
, COrphanTx
> mapOrphanTransactions
;
37 CService
ip(uint32_t i
)
41 return CService(CNetAddr(s
), Params().GetDefaultPort());
46 BOOST_FIXTURE_TEST_SUITE(DoS_tests
, TestingSetup
)
48 BOOST_AUTO_TEST_CASE(DoS_banning
)
50 std::atomic
<bool> interruptDummy(false);
52 connman
->ClearBanned();
53 CAddress
addr1(ip(0xa0b0c001), NODE_NONE
);
54 CNode
dummyNode1(id
++, NODE_NETWORK
, 0, INVALID_SOCKET
, addr1
, 0, 0, "", true);
55 dummyNode1
.SetSendVersion(PROTOCOL_VERSION
);
56 GetNodeSignals().InitializeNode(&dummyNode1
, *connman
);
57 dummyNode1
.nVersion
= 1;
58 dummyNode1
.fSuccessfullyConnected
= true;
59 Misbehaving(dummyNode1
.GetId(), 100); // Should get banned
60 SendMessages(&dummyNode1
, *connman
, interruptDummy
);
61 BOOST_CHECK(connman
->IsBanned(addr1
));
62 BOOST_CHECK(!connman
->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned
64 CAddress
addr2(ip(0xa0b0c002), NODE_NONE
);
65 CNode
dummyNode2(id
++, NODE_NETWORK
, 0, INVALID_SOCKET
, addr2
, 1, 1, "", true);
66 dummyNode2
.SetSendVersion(PROTOCOL_VERSION
);
67 GetNodeSignals().InitializeNode(&dummyNode2
, *connman
);
68 dummyNode2
.nVersion
= 1;
69 dummyNode2
.fSuccessfullyConnected
= true;
70 Misbehaving(dummyNode2
.GetId(), 50);
71 SendMessages(&dummyNode2
, *connman
, interruptDummy
);
72 BOOST_CHECK(!connman
->IsBanned(addr2
)); // 2 not banned yet...
73 BOOST_CHECK(connman
->IsBanned(addr1
)); // ... but 1 still should be
74 Misbehaving(dummyNode2
.GetId(), 50);
75 SendMessages(&dummyNode2
, *connman
, interruptDummy
);
76 BOOST_CHECK(connman
->IsBanned(addr2
));
79 BOOST_AUTO_TEST_CASE(DoS_banscore
)
81 std::atomic
<bool> interruptDummy(false);
83 connman
->ClearBanned();
84 ForceSetArg("-banscore", "111"); // because 11 is my favorite number
85 CAddress
addr1(ip(0xa0b0c001), NODE_NONE
);
86 CNode
dummyNode1(id
++, NODE_NETWORK
, 0, INVALID_SOCKET
, addr1
, 3, 1, "", true);
87 dummyNode1
.SetSendVersion(PROTOCOL_VERSION
);
88 GetNodeSignals().InitializeNode(&dummyNode1
, *connman
);
89 dummyNode1
.nVersion
= 1;
90 dummyNode1
.fSuccessfullyConnected
= true;
91 Misbehaving(dummyNode1
.GetId(), 100);
92 SendMessages(&dummyNode1
, *connman
, interruptDummy
);
93 BOOST_CHECK(!connman
->IsBanned(addr1
));
94 Misbehaving(dummyNode1
.GetId(), 10);
95 SendMessages(&dummyNode1
, *connman
, interruptDummy
);
96 BOOST_CHECK(!connman
->IsBanned(addr1
));
97 Misbehaving(dummyNode1
.GetId(), 1);
98 SendMessages(&dummyNode1
, *connman
, interruptDummy
);
99 BOOST_CHECK(connman
->IsBanned(addr1
));
100 ForceSetArg("-banscore", std::to_string(DEFAULT_BANSCORE_THRESHOLD
));
103 BOOST_AUTO_TEST_CASE(DoS_bantime
)
105 std::atomic
<bool> interruptDummy(false);
107 connman
->ClearBanned();
108 int64_t nStartTime
= GetTime();
109 SetMockTime(nStartTime
); // Overrides future calls to GetTime()
111 CAddress
addr(ip(0xa0b0c001), NODE_NONE
);
112 CNode
dummyNode(id
++, NODE_NETWORK
, 0, INVALID_SOCKET
, addr
, 4, 4, "", true);
113 dummyNode
.SetSendVersion(PROTOCOL_VERSION
);
114 GetNodeSignals().InitializeNode(&dummyNode
, *connman
);
115 dummyNode
.nVersion
= 1;
116 dummyNode
.fSuccessfullyConnected
= true;
118 Misbehaving(dummyNode
.GetId(), 100);
119 SendMessages(&dummyNode
, *connman
, interruptDummy
);
120 BOOST_CHECK(connman
->IsBanned(addr
));
122 SetMockTime(nStartTime
+60*60);
123 BOOST_CHECK(connman
->IsBanned(addr
));
125 SetMockTime(nStartTime
+60*60*24+1);
126 BOOST_CHECK(!connman
->IsBanned(addr
));
129 CTransactionRef
RandomOrphan()
131 std::map
<uint256
, COrphanTx
>::iterator it
;
132 it
= mapOrphanTransactions
.lower_bound(GetRandHash());
133 if (it
== mapOrphanTransactions
.end())
134 it
= mapOrphanTransactions
.begin();
135 return it
->second
.tx
;
138 BOOST_AUTO_TEST_CASE(DoS_mapOrphans
)
141 key
.MakeNewKey(true);
142 CBasicKeyStore keystore
;
143 keystore
.AddKey(key
);
145 // 50 orphan transactions:
146 for (int i
= 0; i
< 50; i
++)
148 CMutableTransaction tx
;
150 tx
.vin
[0].prevout
.n
= 0;
151 tx
.vin
[0].prevout
.hash
= GetRandHash();
152 tx
.vin
[0].scriptSig
<< OP_1
;
154 tx
.vout
[0].nValue
= 1*CENT
;
155 tx
.vout
[0].scriptPubKey
= GetScriptForDestination(key
.GetPubKey().GetID());
157 AddOrphanTx(MakeTransactionRef(tx
), i
);
160 // ... and 50 that depend on other orphans:
161 for (int i
= 0; i
< 50; i
++)
163 CTransactionRef txPrev
= RandomOrphan();
165 CMutableTransaction tx
;
167 tx
.vin
[0].prevout
.n
= 0;
168 tx
.vin
[0].prevout
.hash
= txPrev
->GetHash();
170 tx
.vout
[0].nValue
= 1*CENT
;
171 tx
.vout
[0].scriptPubKey
= GetScriptForDestination(key
.GetPubKey().GetID());
172 SignSignature(keystore
, *txPrev
, tx
, 0, SIGHASH_ALL
);
174 AddOrphanTx(MakeTransactionRef(tx
), i
);
177 // This really-big orphan should be ignored:
178 for (int i
= 0; i
< 10; i
++)
180 CTransactionRef txPrev
= RandomOrphan();
182 CMutableTransaction tx
;
184 tx
.vout
[0].nValue
= 1*CENT
;
185 tx
.vout
[0].scriptPubKey
= GetScriptForDestination(key
.GetPubKey().GetID());
187 for (unsigned int j
= 0; j
< tx
.vin
.size(); j
++)
189 tx
.vin
[j
].prevout
.n
= j
;
190 tx
.vin
[j
].prevout
.hash
= txPrev
->GetHash();
192 SignSignature(keystore
, *txPrev
, tx
, 0, SIGHASH_ALL
);
193 // Re-use same signature for other inputs
194 // (they don't have to be valid for this test)
195 for (unsigned int j
= 1; j
< tx
.vin
.size(); j
++)
196 tx
.vin
[j
].scriptSig
= tx
.vin
[0].scriptSig
;
198 BOOST_CHECK(!AddOrphanTx(MakeTransactionRef(tx
), i
));
201 // Test EraseOrphansFor:
202 for (NodeId i
= 0; i
< 3; i
++)
204 size_t sizeBefore
= mapOrphanTransactions
.size();
206 BOOST_CHECK(mapOrphanTransactions
.size() < sizeBefore
);
209 // Test LimitOrphanTxSize() function:
210 LimitOrphanTxSize(40);
211 BOOST_CHECK(mapOrphanTransactions
.size() <= 40);
212 LimitOrphanTxSize(10);
213 BOOST_CHECK(mapOrphanTransactions
.size() <= 10);
214 LimitOrphanTxSize(0);
215 BOOST_CHECK(mapOrphanTransactions
.empty());
218 BOOST_AUTO_TEST_SUITE_END()