aboutsummaryrefslogtreecommitdiff
path: root/src/test/denialofservice_tests.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/denialofservice_tests.cpp')
-rw-r--r--src/test/denialofservice_tests.cpp111
1 files changed, 72 insertions, 39 deletions
diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp
index fdf7397bff..bcb9a7c181 100644
--- a/src/test/denialofservice_tests.cpp
+++ b/src/test/denialofservice_tests.cpp
@@ -1,9 +1,10 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// Unit tests for denial-of-service detection/prevention code
+#include <banman.h>
#include <chainparams.h>
#include <keystore.h>
#include <net.h>
@@ -11,15 +12,32 @@
#include <pow.h>
#include <script/sign.h>
#include <serialize.h>
-#include <util.h>
+#include <util/system.h>
#include <validation.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <stdint.h>
#include <boost/test/unit_test.hpp>
+struct CConnmanTest : public CConnman {
+ using CConnman::CConnman;
+ void AddNode(CNode& node)
+ {
+ LOCK(cs_vNodes);
+ vNodes.push_back(&node);
+ }
+ void ClearNodes()
+ {
+ LOCK(cs_vNodes);
+ for (CNode* node : vNodes) {
+ delete node;
+ }
+ vNodes.clear();
+ }
+};
+
// Tests these internal-to-net_processing.cpp methods:
extern bool AddOrphanTx(const CTransactionRef& tx, NodeId peer);
extern void EraseOrphansFor(NodeId peer);
@@ -31,7 +49,8 @@ struct COrphanTx {
NodeId fromPeer;
int64_t nTimeExpire;
};
-extern std::map<uint256, COrphanTx> mapOrphanTransactions;
+extern CCriticalSection g_cs_orphans;
+extern std::map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(g_cs_orphans);
static CService ip(uint32_t i)
{
@@ -56,6 +75,8 @@ BOOST_FIXTURE_TEST_SUITE(denialofservice_tests, TestingSetup)
// work.
BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
{
+ auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
+ auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), nullptr, scheduler, false);
// Mock an outbound peer
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
@@ -76,7 +97,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
// Test starts here
{
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode1); // should result in getheaders
+ BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in getheaders
}
{
LOCK2(cs_main, dummyNode1.cs_vSend);
@@ -89,7 +110,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
SetMockTime(nStartTime+21*60);
{
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode1); // should result in getheaders
+ BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in getheaders
}
{
LOCK2(cs_main, dummyNode1.cs_vSend);
@@ -99,7 +120,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
SetMockTime(nStartTime+24*60);
{
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode1); // should result in disconnect
+ BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in disconnect
}
BOOST_CHECK(dummyNode1.fDisconnect == true);
SetMockTime(0);
@@ -108,9 +129,9 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
}
-static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerLogicValidation &peerLogic)
+static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerLogicValidation &peerLogic, CConnmanTest* connman)
{
- CAddress addr(ip(GetRandInt(0xffffffff)), NODE_NONE);
+ CAddress addr(ip(g_insecure_rand_ctx.randbits(32)), NODE_NONE);
vNodes.emplace_back(new CNode(id++, ServiceFlags(NODE_NETWORK|NODE_WITNESS), 0, INVALID_SOCKET, addr, 0, 0, CAddress(), "", /*fInboundIn=*/ false));
CNode &node = *vNodes.back();
node.SetSendVersion(PROTOCOL_VERSION);
@@ -119,11 +140,14 @@ static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerLogicValidat
node.nVersion = 1;
node.fSuccessfullyConnected = true;
- CConnmanTest::AddNode(node);
+ connman->AddNode(node);
}
BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
{
+ auto connman = MakeUnique<CConnmanTest>(0x1337, 0x1337);
+ auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), nullptr, scheduler, false);
+
const Consensus::Params& consensusParams = Params().GetConsensus();
constexpr int nMaxOutbound = 8;
CConnman::Options options;
@@ -136,7 +160,7 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
// Mock some outbound peers
for (int i=0; i<nMaxOutbound; ++i) {
- AddRandomOutboundPeer(vNodes, *peerLogic);
+ AddRandomOutboundPeer(vNodes, *peerLogic, connman.get());
}
peerLogic->CheckForStaleTipAndEvictPeers(consensusParams);
@@ -161,7 +185,7 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
// If we add one more peer, something should get marked for eviction
// on the next check (since we're mocking the time to be in the future, the
// required time connected check should be satisfied).
- AddRandomOutboundPeer(vNodes, *peerLogic);
+ AddRandomOutboundPeer(vNodes, *peerLogic, connman.get());
peerLogic->CheckForStaleTipAndEvictPeers(consensusParams);
for (int i=0; i<nMaxOutbound; ++i) {
@@ -188,13 +212,16 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
peerLogic->FinalizeNode(node->GetId(), dummy);
}
- CConnmanTest::ClearNodes();
+ connman->ClearNodes();
}
BOOST_AUTO_TEST_CASE(DoS_banning)
{
+ auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
+ auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
+ auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), scheduler, false);
- connman->ClearBanned();
+ banman->ClearBanned();
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", true);
dummyNode1.SetSendVersion(PROTOCOL_VERSION);
@@ -207,10 +234,10 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
}
{
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode1);
+ BOOST_CHECK(peerLogic->SendMessages(&dummyNode1));
}
- BOOST_CHECK(connman->IsBanned(addr1));
- BOOST_CHECK(!connman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned
+ BOOST_CHECK(banman->IsBanned(addr1));
+ BOOST_CHECK(!banman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned
CAddress addr2(ip(0xa0b0c002), NODE_NONE);
CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, 1, 1, CAddress(), "", true);
@@ -224,19 +251,19 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
}
{
LOCK2(cs_main, dummyNode2.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode2);
+ BOOST_CHECK(peerLogic->SendMessages(&dummyNode2));
}
- BOOST_CHECK(!connman->IsBanned(addr2)); // 2 not banned yet...
- BOOST_CHECK(connman->IsBanned(addr1)); // ... but 1 still should be
+ BOOST_CHECK(!banman->IsBanned(addr2)); // 2 not banned yet...
+ BOOST_CHECK(banman->IsBanned(addr1)); // ... but 1 still should be
{
LOCK(cs_main);
Misbehaving(dummyNode2.GetId(), 50);
}
{
LOCK2(cs_main, dummyNode2.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode2);
+ BOOST_CHECK(peerLogic->SendMessages(&dummyNode2));
}
- BOOST_CHECK(connman->IsBanned(addr2));
+ BOOST_CHECK(banman->IsBanned(addr2));
bool dummy;
peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
@@ -245,8 +272,11 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
BOOST_AUTO_TEST_CASE(DoS_banscore)
{
+ auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
+ auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
+ auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), scheduler, false);
- connman->ClearBanned();
+ banman->ClearBanned();
gArgs.ForceSetArg("-banscore", "111"); // because 11 is my favorite number
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 3, 1, CAddress(), "", true);
@@ -260,27 +290,27 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
}
{
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode1);
+ BOOST_CHECK(peerLogic->SendMessages(&dummyNode1));
}
- BOOST_CHECK(!connman->IsBanned(addr1));
+ BOOST_CHECK(!banman->IsBanned(addr1));
{
LOCK(cs_main);
Misbehaving(dummyNode1.GetId(), 10);
}
{
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode1);
+ BOOST_CHECK(peerLogic->SendMessages(&dummyNode1));
}
- BOOST_CHECK(!connman->IsBanned(addr1));
+ BOOST_CHECK(!banman->IsBanned(addr1));
{
LOCK(cs_main);
Misbehaving(dummyNode1.GetId(), 1);
}
{
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode1);
+ BOOST_CHECK(peerLogic->SendMessages(&dummyNode1));
}
- BOOST_CHECK(connman->IsBanned(addr1));
+ BOOST_CHECK(banman->IsBanned(addr1));
gArgs.ForceSetArg("-banscore", std::to_string(DEFAULT_BANSCORE_THRESHOLD));
bool dummy;
@@ -289,8 +319,11 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
BOOST_AUTO_TEST_CASE(DoS_bantime)
{
+ auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
+ auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
+ auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), scheduler, false);
- connman->ClearBanned();
+ banman->ClearBanned();
int64_t nStartTime = GetTime();
SetMockTime(nStartTime); // Overrides future calls to GetTime()
@@ -307,15 +340,15 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
}
{
LOCK2(cs_main, dummyNode.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode);
+ BOOST_CHECK(peerLogic->SendMessages(&dummyNode));
}
- BOOST_CHECK(connman->IsBanned(addr));
+ BOOST_CHECK(banman->IsBanned(addr));
SetMockTime(nStartTime+60*60);
- BOOST_CHECK(connman->IsBanned(addr));
+ BOOST_CHECK(banman->IsBanned(addr));
SetMockTime(nStartTime+60*60*24+1);
- BOOST_CHECK(!connman->IsBanned(addr));
+ BOOST_CHECK(!banman->IsBanned(addr));
bool dummy;
peerLogic->FinalizeNode(dummyNode.GetId(), dummy);
@@ -324,7 +357,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
static CTransactionRef RandomOrphan()
{
std::map<uint256, COrphanTx>::iterator it;
- LOCK(cs_main);
+ LOCK2(cs_main, g_cs_orphans);
it = mapOrphanTransactions.lower_bound(InsecureRand256());
if (it == mapOrphanTransactions.end())
it = mapOrphanTransactions.begin();
@@ -336,7 +369,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
CKey key;
key.MakeNewKey(true);
CBasicKeyStore keystore;
- keystore.AddKey(key);
+ BOOST_CHECK(keystore.AddKey(key));
// 50 orphan transactions:
for (int i = 0; i < 50; i++)
@@ -365,7 +398,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
tx.vout.resize(1);
tx.vout[0].nValue = 1*CENT;
tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
- SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL);
+ BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL));
AddOrphanTx(MakeTransactionRef(tx), i);
}
@@ -385,7 +418,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
tx.vin[j].prevout.n = j;
tx.vin[j].prevout.hash = txPrev->GetHash();
}
- SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL);
+ BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL));
// Re-use same signature for other inputs
// (they don't have to be valid for this test)
for (unsigned int j = 1; j < tx.vin.size(); j++)
@@ -394,7 +427,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
BOOST_CHECK(!AddOrphanTx(MakeTransactionRef(tx), i));
}
- LOCK(cs_main);
+ LOCK2(cs_main, g_cs_orphans);
// Test EraseOrphansFor:
for (NodeId i = 0; i < 3; i++)
{