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/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
);
32 extern std::map
<uint256
, COrphanTx
> mapOrphanTransactions
;
34 CService
ip(uint32_t i
)
38 return CService(CNetAddr(s
), Params().GetDefaultPort());
43 BOOST_FIXTURE_TEST_SUITE(DoS_tests
, TestingSetup
)
45 BOOST_AUTO_TEST_CASE(DoS_banning
)
47 std::atomic
<bool> interruptDummy(false);
49 connman
->ClearBanned();
50 CAddress
addr1(ip(0xa0b0c001), NODE_NONE
);
51 CNode
dummyNode1(id
++, NODE_NETWORK
, 0, INVALID_SOCKET
, addr1
, 0, 0, CAddress(), "", true);
52 dummyNode1
.SetSendVersion(PROTOCOL_VERSION
);
53 GetNodeSignals().InitializeNode(&dummyNode1
, *connman
);
54 dummyNode1
.nVersion
= 1;
55 dummyNode1
.fSuccessfullyConnected
= true;
56 Misbehaving(dummyNode1
.GetId(), 100); // Should get banned
57 SendMessages(&dummyNode1
, *connman
, interruptDummy
);
58 BOOST_CHECK(connman
->IsBanned(addr1
));
59 BOOST_CHECK(!connman
->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned
61 CAddress
addr2(ip(0xa0b0c002), NODE_NONE
);
62 CNode
dummyNode2(id
++, NODE_NETWORK
, 0, INVALID_SOCKET
, addr2
, 1, 1, CAddress(), "", true);
63 dummyNode2
.SetSendVersion(PROTOCOL_VERSION
);
64 GetNodeSignals().InitializeNode(&dummyNode2
, *connman
);
65 dummyNode2
.nVersion
= 1;
66 dummyNode2
.fSuccessfullyConnected
= true;
67 Misbehaving(dummyNode2
.GetId(), 50);
68 SendMessages(&dummyNode2
, *connman
, interruptDummy
);
69 BOOST_CHECK(!connman
->IsBanned(addr2
)); // 2 not banned yet...
70 BOOST_CHECK(connman
->IsBanned(addr1
)); // ... but 1 still should be
71 Misbehaving(dummyNode2
.GetId(), 50);
72 SendMessages(&dummyNode2
, *connman
, interruptDummy
);
73 BOOST_CHECK(connman
->IsBanned(addr2
));
76 BOOST_AUTO_TEST_CASE(DoS_banscore
)
78 std::atomic
<bool> interruptDummy(false);
80 connman
->ClearBanned();
81 gArgs
.ForceSetArg("-banscore", "111"); // because 11 is my favorite number
82 CAddress
addr1(ip(0xa0b0c001), NODE_NONE
);
83 CNode
dummyNode1(id
++, NODE_NETWORK
, 0, INVALID_SOCKET
, addr1
, 3, 1, CAddress(), "", true);
84 dummyNode1
.SetSendVersion(PROTOCOL_VERSION
);
85 GetNodeSignals().InitializeNode(&dummyNode1
, *connman
);
86 dummyNode1
.nVersion
= 1;
87 dummyNode1
.fSuccessfullyConnected
= true;
88 Misbehaving(dummyNode1
.GetId(), 100);
89 SendMessages(&dummyNode1
, *connman
, interruptDummy
);
90 BOOST_CHECK(!connman
->IsBanned(addr1
));
91 Misbehaving(dummyNode1
.GetId(), 10);
92 SendMessages(&dummyNode1
, *connman
, interruptDummy
);
93 BOOST_CHECK(!connman
->IsBanned(addr1
));
94 Misbehaving(dummyNode1
.GetId(), 1);
95 SendMessages(&dummyNode1
, *connman
, interruptDummy
);
96 BOOST_CHECK(connman
->IsBanned(addr1
));
97 gArgs
.ForceSetArg("-banscore", std::to_string(DEFAULT_BANSCORE_THRESHOLD
));
100 BOOST_AUTO_TEST_CASE(DoS_bantime
)
102 std::atomic
<bool> interruptDummy(false);
104 connman
->ClearBanned();
105 int64_t nStartTime
= GetTime();
106 SetMockTime(nStartTime
); // Overrides future calls to GetTime()
108 CAddress
addr(ip(0xa0b0c001), NODE_NONE
);
109 CNode
dummyNode(id
++, NODE_NETWORK
, 0, INVALID_SOCKET
, addr
, 4, 4, CAddress(), "", true);
110 dummyNode
.SetSendVersion(PROTOCOL_VERSION
);
111 GetNodeSignals().InitializeNode(&dummyNode
, *connman
);
112 dummyNode
.nVersion
= 1;
113 dummyNode
.fSuccessfullyConnected
= true;
115 Misbehaving(dummyNode
.GetId(), 100);
116 SendMessages(&dummyNode
, *connman
, interruptDummy
);
117 BOOST_CHECK(connman
->IsBanned(addr
));
119 SetMockTime(nStartTime
+60*60);
120 BOOST_CHECK(connman
->IsBanned(addr
));
122 SetMockTime(nStartTime
+60*60*24+1);
123 BOOST_CHECK(!connman
->IsBanned(addr
));
126 CTransactionRef
RandomOrphan()
128 std::map
<uint256
, COrphanTx
>::iterator it
;
129 it
= mapOrphanTransactions
.lower_bound(InsecureRand256());
130 if (it
== mapOrphanTransactions
.end())
131 it
= mapOrphanTransactions
.begin();
132 return it
->second
.tx
;
135 BOOST_AUTO_TEST_CASE(DoS_mapOrphans
)
138 key
.MakeNewKey(true);
139 CBasicKeyStore keystore
;
140 keystore
.AddKey(key
);
142 // 50 orphan transactions:
143 for (int i
= 0; i
< 50; i
++)
145 CMutableTransaction tx
;
147 tx
.vin
[0].prevout
.n
= 0;
148 tx
.vin
[0].prevout
.hash
= InsecureRand256();
149 tx
.vin
[0].scriptSig
<< OP_1
;
151 tx
.vout
[0].nValue
= 1*CENT
;
152 tx
.vout
[0].scriptPubKey
= GetScriptForDestination(key
.GetPubKey().GetID());
154 AddOrphanTx(MakeTransactionRef(tx
), i
);
157 // ... and 50 that depend on other orphans:
158 for (int i
= 0; i
< 50; i
++)
160 CTransactionRef txPrev
= RandomOrphan();
162 CMutableTransaction tx
;
164 tx
.vin
[0].prevout
.n
= 0;
165 tx
.vin
[0].prevout
.hash
= txPrev
->GetHash();
167 tx
.vout
[0].nValue
= 1*CENT
;
168 tx
.vout
[0].scriptPubKey
= GetScriptForDestination(key
.GetPubKey().GetID());
169 SignSignature(keystore
, *txPrev
, tx
, 0, SIGHASH_ALL
);
171 AddOrphanTx(MakeTransactionRef(tx
), i
);
174 // This really-big orphan should be ignored:
175 for (int i
= 0; i
< 10; i
++)
177 CTransactionRef txPrev
= RandomOrphan();
179 CMutableTransaction tx
;
181 tx
.vout
[0].nValue
= 1*CENT
;
182 tx
.vout
[0].scriptPubKey
= GetScriptForDestination(key
.GetPubKey().GetID());
184 for (unsigned int j
= 0; j
< tx
.vin
.size(); j
++)
186 tx
.vin
[j
].prevout
.n
= j
;
187 tx
.vin
[j
].prevout
.hash
= txPrev
->GetHash();
189 SignSignature(keystore
, *txPrev
, tx
, 0, SIGHASH_ALL
);
190 // Re-use same signature for other inputs
191 // (they don't have to be valid for this test)
192 for (unsigned int j
= 1; j
< tx
.vin
.size(); j
++)
193 tx
.vin
[j
].scriptSig
= tx
.vin
[0].scriptSig
;
195 BOOST_CHECK(!AddOrphanTx(MakeTransactionRef(tx
), i
));
198 // Test EraseOrphansFor:
199 for (NodeId i
= 0; i
< 3; i
++)
201 size_t sizeBefore
= mapOrphanTransactions
.size();
203 BOOST_CHECK(mapOrphanTransactions
.size() < sizeBefore
);
206 // Test LimitOrphanTxSize() function:
207 LimitOrphanTxSize(40);
208 BOOST_CHECK(mapOrphanTransactions
.size() <= 40);
209 LimitOrphanTxSize(10);
210 BOOST_CHECK(mapOrphanTransactions
.size() <= 10);
211 LimitOrphanTxSize(0);
212 BOOST_CHECK(mapOrphanTransactions
.empty());
215 BOOST_AUTO_TEST_SUITE_END()