Add CConnmanTest to mutate g_connman in tests
[bitcoinplatinum.git] / src / test / DoS_tests.cpp
blob7bcf304833f175596968cec2f3a6cb0dc30f21ca
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"
8 #include "keystore.h"
9 #include "net.h"
10 #include "net_processing.h"
11 #include "pow.h"
12 #include "script/sign.h"
13 #include "serialize.h"
14 #include "util.h"
15 #include "validation.h"
17 #include "test/test_bitcoin.h"
19 #include <stdint.h>
21 #include <boost/test/unit_test.hpp>
23 // Tests these internal-to-net_processing.cpp methods:
24 extern bool AddOrphanTx(const CTransactionRef& tx, NodeId peer);
25 extern void EraseOrphansFor(NodeId peer);
26 extern unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans);
27 struct COrphanTx {
28 CTransactionRef tx;
29 NodeId fromPeer;
30 int64_t nTimeExpire;
32 extern std::map<uint256, COrphanTx> mapOrphanTransactions;
34 CService ip(uint32_t i)
36 struct in_addr s;
37 s.s_addr = i;
38 return CService(CNetAddr(s), Params().GetDefaultPort());
41 static NodeId id = 0;
43 BOOST_FIXTURE_TEST_SUITE(DoS_tests, TestingSetup)
45 // Test eviction of an outbound peer whose chain never advances
46 // Mock a node connection, and use mocktime to simulate a peer
47 // which never sends any headers messages. PeerLogic should
48 // decide to evict that outbound peer, after the appropriate timeouts.
49 // Note that we protect 4 outbound nodes from being subject to
50 // this logic; this test takes advantage of that protection only
51 // being applied to nodes which send headers with sufficient
52 // work.
53 BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
55 std::atomic<bool> interruptDummy(false);
57 // Mock an outbound peer
58 CAddress addr1(ip(0xa0b0c001), NODE_NONE);
59 CNode dummyNode1(id++, ServiceFlags(NODE_NETWORK|NODE_WITNESS), 0, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", /*fInboundIn=*/ false);
60 dummyNode1.SetSendVersion(PROTOCOL_VERSION);
62 peerLogic->InitializeNode(&dummyNode1);
63 dummyNode1.nVersion = 1;
64 dummyNode1.fSuccessfullyConnected = true;
66 // This test requires that we have a chain with non-zero work.
67 BOOST_CHECK(chainActive.Tip() != nullptr);
68 BOOST_CHECK(chainActive.Tip()->nChainWork > 0);
70 // Test starts here
71 peerLogic->SendMessages(&dummyNode1, interruptDummy); // should result in getheaders
72 BOOST_CHECK(dummyNode1.vSendMsg.size() > 0);
73 dummyNode1.vSendMsg.clear();
75 int64_t nStartTime = GetTime();
76 // Wait 21 minutes
77 SetMockTime(nStartTime+21*60);
78 peerLogic->SendMessages(&dummyNode1, interruptDummy); // should result in getheaders
79 BOOST_CHECK(dummyNode1.vSendMsg.size() > 0);
80 // Wait 3 more minutes
81 SetMockTime(nStartTime+24*60);
82 peerLogic->SendMessages(&dummyNode1, interruptDummy); // should result in disconnect
83 BOOST_CHECK(dummyNode1.fDisconnect == true);
84 SetMockTime(0);
86 bool dummy;
87 peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
90 BOOST_AUTO_TEST_CASE(DoS_banning)
92 std::atomic<bool> interruptDummy(false);
94 connman->ClearBanned();
95 CAddress addr1(ip(0xa0b0c001), NODE_NONE);
96 CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", true);
97 dummyNode1.SetSendVersion(PROTOCOL_VERSION);
98 peerLogic->InitializeNode(&dummyNode1);
99 dummyNode1.nVersion = 1;
100 dummyNode1.fSuccessfullyConnected = true;
101 Misbehaving(dummyNode1.GetId(), 100); // Should get banned
102 peerLogic->SendMessages(&dummyNode1, interruptDummy);
103 BOOST_CHECK(connman->IsBanned(addr1));
104 BOOST_CHECK(!connman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned
106 CAddress addr2(ip(0xa0b0c002), NODE_NONE);
107 CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, 1, 1, CAddress(), "", true);
108 dummyNode2.SetSendVersion(PROTOCOL_VERSION);
109 peerLogic->InitializeNode(&dummyNode2);
110 dummyNode2.nVersion = 1;
111 dummyNode2.fSuccessfullyConnected = true;
112 Misbehaving(dummyNode2.GetId(), 50);
113 peerLogic->SendMessages(&dummyNode2, interruptDummy);
114 BOOST_CHECK(!connman->IsBanned(addr2)); // 2 not banned yet...
115 BOOST_CHECK(connman->IsBanned(addr1)); // ... but 1 still should be
116 Misbehaving(dummyNode2.GetId(), 50);
117 peerLogic->SendMessages(&dummyNode2, interruptDummy);
118 BOOST_CHECK(connman->IsBanned(addr2));
120 bool dummy;
121 peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
122 peerLogic->FinalizeNode(dummyNode2.GetId(), dummy);
125 BOOST_AUTO_TEST_CASE(DoS_banscore)
127 std::atomic<bool> interruptDummy(false);
129 connman->ClearBanned();
130 gArgs.ForceSetArg("-banscore", "111"); // because 11 is my favorite number
131 CAddress addr1(ip(0xa0b0c001), NODE_NONE);
132 CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 3, 1, CAddress(), "", true);
133 dummyNode1.SetSendVersion(PROTOCOL_VERSION);
134 peerLogic->InitializeNode(&dummyNode1);
135 dummyNode1.nVersion = 1;
136 dummyNode1.fSuccessfullyConnected = true;
137 Misbehaving(dummyNode1.GetId(), 100);
138 peerLogic->SendMessages(&dummyNode1, interruptDummy);
139 BOOST_CHECK(!connman->IsBanned(addr1));
140 Misbehaving(dummyNode1.GetId(), 10);
141 peerLogic->SendMessages(&dummyNode1, interruptDummy);
142 BOOST_CHECK(!connman->IsBanned(addr1));
143 Misbehaving(dummyNode1.GetId(), 1);
144 peerLogic->SendMessages(&dummyNode1, interruptDummy);
145 BOOST_CHECK(connman->IsBanned(addr1));
146 gArgs.ForceSetArg("-banscore", std::to_string(DEFAULT_BANSCORE_THRESHOLD));
148 bool dummy;
149 peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
152 BOOST_AUTO_TEST_CASE(DoS_bantime)
154 std::atomic<bool> interruptDummy(false);
156 connman->ClearBanned();
157 int64_t nStartTime = GetTime();
158 SetMockTime(nStartTime); // Overrides future calls to GetTime()
160 CAddress addr(ip(0xa0b0c001), NODE_NONE);
161 CNode dummyNode(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr, 4, 4, CAddress(), "", true);
162 dummyNode.SetSendVersion(PROTOCOL_VERSION);
163 peerLogic->InitializeNode(&dummyNode);
164 dummyNode.nVersion = 1;
165 dummyNode.fSuccessfullyConnected = true;
167 Misbehaving(dummyNode.GetId(), 100);
168 peerLogic->SendMessages(&dummyNode, interruptDummy);
169 BOOST_CHECK(connman->IsBanned(addr));
171 SetMockTime(nStartTime+60*60);
172 BOOST_CHECK(connman->IsBanned(addr));
174 SetMockTime(nStartTime+60*60*24+1);
175 BOOST_CHECK(!connman->IsBanned(addr));
177 bool dummy;
178 peerLogic->FinalizeNode(dummyNode.GetId(), dummy);
181 CTransactionRef RandomOrphan()
183 std::map<uint256, COrphanTx>::iterator it;
184 it = mapOrphanTransactions.lower_bound(InsecureRand256());
185 if (it == mapOrphanTransactions.end())
186 it = mapOrphanTransactions.begin();
187 return it->second.tx;
190 BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
192 CKey key;
193 key.MakeNewKey(true);
194 CBasicKeyStore keystore;
195 keystore.AddKey(key);
197 // 50 orphan transactions:
198 for (int i = 0; i < 50; i++)
200 CMutableTransaction tx;
201 tx.vin.resize(1);
202 tx.vin[0].prevout.n = 0;
203 tx.vin[0].prevout.hash = InsecureRand256();
204 tx.vin[0].scriptSig << OP_1;
205 tx.vout.resize(1);
206 tx.vout[0].nValue = 1*CENT;
207 tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
209 AddOrphanTx(MakeTransactionRef(tx), i);
212 // ... and 50 that depend on other orphans:
213 for (int i = 0; i < 50; i++)
215 CTransactionRef txPrev = RandomOrphan();
217 CMutableTransaction tx;
218 tx.vin.resize(1);
219 tx.vin[0].prevout.n = 0;
220 tx.vin[0].prevout.hash = txPrev->GetHash();
221 tx.vout.resize(1);
222 tx.vout[0].nValue = 1*CENT;
223 tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
224 SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL);
226 AddOrphanTx(MakeTransactionRef(tx), i);
229 // This really-big orphan should be ignored:
230 for (int i = 0; i < 10; i++)
232 CTransactionRef txPrev = RandomOrphan();
234 CMutableTransaction tx;
235 tx.vout.resize(1);
236 tx.vout[0].nValue = 1*CENT;
237 tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
238 tx.vin.resize(2777);
239 for (unsigned int j = 0; j < tx.vin.size(); j++)
241 tx.vin[j].prevout.n = j;
242 tx.vin[j].prevout.hash = txPrev->GetHash();
244 SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL);
245 // Re-use same signature for other inputs
246 // (they don't have to be valid for this test)
247 for (unsigned int j = 1; j < tx.vin.size(); j++)
248 tx.vin[j].scriptSig = tx.vin[0].scriptSig;
250 BOOST_CHECK(!AddOrphanTx(MakeTransactionRef(tx), i));
253 // Test EraseOrphansFor:
254 for (NodeId i = 0; i < 3; i++)
256 size_t sizeBefore = mapOrphanTransactions.size();
257 EraseOrphansFor(i);
258 BOOST_CHECK(mapOrphanTransactions.size() < sizeBefore);
261 // Test LimitOrphanTxSize() function:
262 LimitOrphanTxSize(40);
263 BOOST_CHECK(mapOrphanTransactions.size() <= 40);
264 LimitOrphanTxSize(10);
265 BOOST_CHECK(mapOrphanTransactions.size() <= 10);
266 LimitOrphanTxSize(0);
267 BOOST_CHECK(mapOrphanTransactions.empty());
270 BOOST_AUTO_TEST_SUITE_END()