Changeset View
Changeset View
Standalone View
Standalone View
src/test/DoS_tests.cpp
Show All 15 Lines | |||||
#include "validation.h" | #include "validation.h" | ||||
#include "test/test_bitcoin.h" | #include "test/test_bitcoin.h" | ||||
#include <cstdint> | #include <cstdint> | ||||
#include <boost/test/unit_test.hpp> | #include <boost/test/unit_test.hpp> | ||||
// Tests these internal-to-net_processing.cpp methods: | |||||
extern bool AddOrphanTx(const CTransactionRef &tx, NodeId peer); | |||||
extern void EraseOrphansFor(NodeId peer); | |||||
extern unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans); | |||||
struct COrphanTx { | |||||
CTransactionRef tx; | |||||
NodeId fromPeer; | |||||
int64_t nTimeExpire; | |||||
}; | |||||
extern std::map<uint256, COrphanTx> mapOrphanTransactions; | |||||
CService ip(uint32_t i) { | CService ip(uint32_t i) { | ||||
struct in_addr s; | struct in_addr s; | ||||
s.s_addr = i; | s.s_addr = i; | ||||
return CService(CNetAddr(s), Params().GetDefaultPort()); | return CService(CNetAddr(s), Params().GetDefaultPort()); | ||||
} | } | ||||
static NodeId id = 0; | static NodeId id = 0; | ||||
▲ Show 20 Lines • Show All 261 Lines • ▼ Show 20 Lines | BOOST_AUTO_TEST_CASE(DoS_bantime) { | ||||
SetMockTime(nStartTime + 60 * 60 * 24 + 1); | SetMockTime(nStartTime + 60 * 60 * 24 + 1); | ||||
BOOST_CHECK(!connman->IsBanned(addr)); | BOOST_CHECK(!connman->IsBanned(addr)); | ||||
bool dummy; | bool dummy; | ||||
peerLogic->FinalizeNode(config, dummyNode.GetId(), dummy); | peerLogic->FinalizeNode(config, dummyNode.GetId(), dummy); | ||||
} | } | ||||
CTransactionRef RandomOrphan() { | CTransactionRef RandomOrphan() { | ||||
std::map<uint256, COrphanTx>::iterator it; | std::map<uint256, COrphanTx>::const_iterator it; | ||||
LOCK(cs_main); | auto mapOrphans = g_orphanPool.OrphanTransactions(); | ||||
it = mapOrphanTransactions.lower_bound(InsecureRand256()); | it = mapOrphans->lower_bound(InsecureRand256()); | ||||
if (it == mapOrphanTransactions.end()) { | if (it == mapOrphans.end()) { | ||||
it = mapOrphanTransactions.begin(); | it = mapOrphans.begin(); | ||||
} | } | ||||
return it->second.tx; | return it->second.tx; | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(DoS_mapOrphans) { | BOOST_AUTO_TEST_CASE(DoS_mapOrphans) { | ||||
CKey key; | CKey key; | ||||
key.MakeNewKey(true); | key.MakeNewKey(true); | ||||
CBasicKeyStore keystore; | CBasicKeyStore keystore; | ||||
keystore.AddKey(key); | keystore.AddKey(key); | ||||
// 50 orphan transactions: | // 50 orphan transactions: | ||||
for (int i = 0; i < 50; i++) { | for (int i = 0; i < 50; i++) { | ||||
CMutableTransaction tx; | CMutableTransaction tx; | ||||
tx.vin.resize(1); | tx.vin.resize(1); | ||||
tx.vin[0].prevout = COutPoint(InsecureRand256(), 0); | tx.vin[0].prevout = COutPoint(InsecureRand256(), 0); | ||||
tx.vin[0].scriptSig << OP_1; | tx.vin[0].scriptSig << OP_1; | ||||
tx.vout.resize(1); | tx.vout.resize(1); | ||||
tx.vout[0].nValue = 1 * CENT; | tx.vout[0].nValue = 1 * CENT; | ||||
tx.vout[0].scriptPubKey = | tx.vout[0].scriptPubKey = | ||||
GetScriptForDestination(key.GetPubKey().GetID()); | GetScriptForDestination(key.GetPubKey().GetID()); | ||||
AddOrphanTx(MakeTransactionRef(tx), i); | g_orphanPool.AddOrphanTx(MakeTransactionRef(tx), i); | ||||
} | } | ||||
// ... and 50 that depend on other orphans: | // ... and 50 that depend on other orphans: | ||||
for (int i = 0; i < 50; i++) { | for (int i = 0; i < 50; i++) { | ||||
CTransactionRef txPrev = RandomOrphan(); | CTransactionRef txPrev = RandomOrphan(); | ||||
CMutableTransaction tx; | CMutableTransaction tx; | ||||
tx.vin.resize(1); | tx.vin.resize(1); | ||||
tx.vin[0].prevout = COutPoint(txPrev->GetId(), 0); | tx.vin[0].prevout = COutPoint(txPrev->GetId(), 0); | ||||
tx.vout.resize(1); | tx.vout.resize(1); | ||||
tx.vout[0].nValue = 1 * CENT; | tx.vout[0].nValue = 1 * CENT; | ||||
tx.vout[0].scriptPubKey = | tx.vout[0].scriptPubKey = | ||||
GetScriptForDestination(key.GetPubKey().GetID()); | GetScriptForDestination(key.GetPubKey().GetID()); | ||||
SignSignature(keystore, *txPrev, tx, 0, SigHashType()); | SignSignature(keystore, *txPrev, tx, 0, SigHashType()); | ||||
AddOrphanTx(MakeTransactionRef(tx), i); | g_orphanPool.AddOrphanTx(MakeTransactionRef(tx), i); | ||||
} | } | ||||
// This really-big orphan should be ignored: | // This really-big orphan should be ignored: | ||||
for (int i = 0; i < 10; i++) { | for (int i = 0; i < 10; i++) { | ||||
CTransactionRef txPrev = RandomOrphan(); | CTransactionRef txPrev = RandomOrphan(); | ||||
CMutableTransaction tx; | CMutableTransaction tx; | ||||
tx.vout.resize(1); | tx.vout.resize(1); | ||||
tx.vout[0].nValue = 1 * CENT; | tx.vout[0].nValue = 1 * CENT; | ||||
tx.vout[0].scriptPubKey = | tx.vout[0].scriptPubKey = | ||||
GetScriptForDestination(key.GetPubKey().GetID()); | GetScriptForDestination(key.GetPubKey().GetID()); | ||||
tx.vin.resize(2777); | tx.vin.resize(2777); | ||||
for (size_t j = 0; j < tx.vin.size(); j++) { | for (size_t j = 0; j < tx.vin.size(); j++) { | ||||
tx.vin[j].prevout = COutPoint(txPrev->GetId(), j); | tx.vin[j].prevout = COutPoint(txPrev->GetId(), j); | ||||
} | } | ||||
SignSignature(keystore, *txPrev, tx, 0, SigHashType()); | SignSignature(keystore, *txPrev, tx, 0, SigHashType()); | ||||
// Re-use same signature for other inputs | // Re-use same signature for other inputs | ||||
// (they don't have to be valid for this test) | // (they don't have to be valid for this test) | ||||
for (unsigned int j = 1; j < tx.vin.size(); j++) | for (unsigned int j = 1; j < tx.vin.size(); j++) | ||||
tx.vin[j].scriptSig = tx.vin[0].scriptSig; | tx.vin[j].scriptSig = tx.vin[0].scriptSig; | ||||
BOOST_CHECK(!AddOrphanTx(MakeTransactionRef(tx), i)); | BOOST_CHECK(!g_orphanPool.AddOrphanTx(MakeTransactionRef(tx), i)); | ||||
} | } | ||||
LOCK(cs_main); | size_t sizeBefore; | ||||
// Test EraseOrphansFor: | // Test EraseOrphansFor: | ||||
for (NodeId i = 0; i < 3; i++) { | for (NodeId i = 0; i < 3; i++) { | ||||
size_t sizeBefore = mapOrphanTransactions.size(); | { | ||||
EraseOrphansFor(i); | sizeBefore = g_orphanPool.OrphanTransactions()->size(); | ||||
BOOST_CHECK(mapOrphanTransactions.size() < sizeBefore); | } | ||||
g_orphanPool.EraseOrphansFor(i); | |||||
{ BOOST_CHECK(g_orphanPool.OrphanTransactions()->size() < sizeBefore); } | |||||
} | } | ||||
// Test LimitOrphanTxSize() function: | // Test LimitOrphanTxSize() function: | ||||
LimitOrphanTxSize(40); | g_orphanPool.LimitOrphanTxSize(40); | ||||
BOOST_CHECK(mapOrphanTransactions.size() <= 40); | { BOOST_CHECK(g_orphanPool.OrphanTransactions()->size() <= 40); } | ||||
LimitOrphanTxSize(10); | g_orphanPool.LimitOrphanTxSize(10); | ||||
BOOST_CHECK(mapOrphanTransactions.size() <= 10); | { BOOST_CHECK(g_orphanPool.OrphanTransactions()->size() <= 10); } | ||||
LimitOrphanTxSize(0); | g_orphanPool.LimitOrphanTxSize(0); | ||||
BOOST_CHECK(mapOrphanTransactions.empty()); | { BOOST_CHECK(g_orphanPool.OrphanTransactions()->empty()); } | ||||
} | } | ||||
BOOST_AUTO_TEST_SUITE_END() | BOOST_AUTO_TEST_SUITE_END() |