Changeset View
Changeset View
Standalone View
Standalone View
src/test/denialofservice_tests.cpp
Show First 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | // This test requires that we have a chain with non-zero work. | ||||
BOOST_CHECK(::ChainActive().Tip() != nullptr); | BOOST_CHECK(::ChainActive().Tip() != nullptr); | ||||
BOOST_CHECK(::ChainActive().Tip()->nChainWork > 0); | BOOST_CHECK(::ChainActive().Tip()->nChainWork > 0); | ||||
} | } | ||||
// Test starts here | // Test starts here | ||||
{ | { | ||||
LOCK2(cs_main, dummyNode1.cs_sendProcessing); | LOCK2(cs_main, dummyNode1.cs_sendProcessing); | ||||
// should result in getheaders | // should result in getheaders | ||||
peerLogic->SendMessages(config, &dummyNode1, interruptDummy); | BOOST_CHECK( | ||||
peerLogic->SendMessages(config, &dummyNode1, interruptDummy)); | |||||
} | } | ||||
{ | { | ||||
LOCK2(cs_main, dummyNode1.cs_vSend); | LOCK2(cs_main, dummyNode1.cs_vSend); | ||||
BOOST_CHECK(dummyNode1.vSendMsg.size() > 0); | BOOST_CHECK(dummyNode1.vSendMsg.size() > 0); | ||||
dummyNode1.vSendMsg.clear(); | dummyNode1.vSendMsg.clear(); | ||||
} | } | ||||
int64_t nStartTime = GetTime(); | int64_t nStartTime = GetTime(); | ||||
// Wait 21 minutes | // Wait 21 minutes | ||||
SetMockTime(nStartTime + 21 * 60); | SetMockTime(nStartTime + 21 * 60); | ||||
{ | { | ||||
LOCK2(cs_main, dummyNode1.cs_sendProcessing); | LOCK2(cs_main, dummyNode1.cs_sendProcessing); | ||||
// should result in getheaders | // should result in getheaders | ||||
peerLogic->SendMessages(config, &dummyNode1, interruptDummy); | BOOST_CHECK( | ||||
peerLogic->SendMessages(config, &dummyNode1, interruptDummy)); | |||||
} | } | ||||
{ | { | ||||
LOCK2(cs_main, dummyNode1.cs_vSend); | LOCK2(cs_main, dummyNode1.cs_vSend); | ||||
BOOST_CHECK(dummyNode1.vSendMsg.size() > 0); | BOOST_CHECK(dummyNode1.vSendMsg.size() > 0); | ||||
} | } | ||||
// Wait 3 more minutes | // Wait 3 more minutes | ||||
SetMockTime(nStartTime + 24 * 60); | SetMockTime(nStartTime + 24 * 60); | ||||
{ | { | ||||
LOCK2(cs_main, dummyNode1.cs_sendProcessing); | LOCK2(cs_main, dummyNode1.cs_sendProcessing); | ||||
// should result in disconnect | // should result in disconnect | ||||
peerLogic->SendMessages(config, &dummyNode1, interruptDummy); | BOOST_CHECK( | ||||
peerLogic->SendMessages(config, &dummyNode1, interruptDummy)); | |||||
} | } | ||||
BOOST_CHECK(dummyNode1.fDisconnect == true); | BOOST_CHECK(dummyNode1.fDisconnect == true); | ||||
SetMockTime(0); | SetMockTime(0); | ||||
bool dummy; | bool dummy; | ||||
peerLogic->FinalizeNode(config, dummyNode1.GetId(), dummy); | peerLogic->FinalizeNode(config, dummyNode1.GetId(), dummy); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | BOOST_AUTO_TEST_CASE(DoS_banning) { | ||||
dummyNode1.fSuccessfullyConnected = true; | dummyNode1.fSuccessfullyConnected = true; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
// Should get banned. | // Should get banned. | ||||
Misbehaving(dummyNode1.GetId(), 100, ""); | Misbehaving(dummyNode1.GetId(), 100, ""); | ||||
} | } | ||||
{ | { | ||||
LOCK2(cs_main, dummyNode1.cs_sendProcessing); | LOCK2(cs_main, dummyNode1.cs_sendProcessing); | ||||
peerLogic->SendMessages(config, &dummyNode1, interruptDummy); | BOOST_CHECK( | ||||
peerLogic->SendMessages(config, &dummyNode1, interruptDummy)); | |||||
} | } | ||||
BOOST_CHECK(banman->IsBanned(addr1)); | BOOST_CHECK(banman->IsBanned(addr1)); | ||||
// Different IP, not banned. | // Different IP, not banned. | ||||
BOOST_CHECK(!banman->IsBanned(ip(0xa0b0c001 | 0x0000ff00))); | BOOST_CHECK(!banman->IsBanned(ip(0xa0b0c001 | 0x0000ff00))); | ||||
CAddress addr2(ip(0xa0b0c002), NODE_NONE); | CAddress addr2(ip(0xa0b0c002), NODE_NONE); | ||||
CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, 1, 1, | CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, 1, 1, | ||||
CAddress(), "", true); | CAddress(), "", true); | ||||
dummyNode2.SetSendVersion(PROTOCOL_VERSION); | dummyNode2.SetSendVersion(PROTOCOL_VERSION); | ||||
peerLogic->InitializeNode(config, &dummyNode2); | peerLogic->InitializeNode(config, &dummyNode2); | ||||
dummyNode2.nVersion = 1; | dummyNode2.nVersion = 1; | ||||
dummyNode2.fSuccessfullyConnected = true; | dummyNode2.fSuccessfullyConnected = true; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
Misbehaving(dummyNode2.GetId(), 50, ""); | Misbehaving(dummyNode2.GetId(), 50, ""); | ||||
} | } | ||||
{ | { | ||||
LOCK2(cs_main, dummyNode2.cs_sendProcessing); | LOCK2(cs_main, dummyNode2.cs_sendProcessing); | ||||
peerLogic->SendMessages(config, &dummyNode2, interruptDummy); | BOOST_CHECK( | ||||
peerLogic->SendMessages(config, &dummyNode2, interruptDummy)); | |||||
} | } | ||||
// 2 not banned yet... | // 2 not banned yet... | ||||
BOOST_CHECK(!banman->IsBanned(addr2)); | BOOST_CHECK(!banman->IsBanned(addr2)); | ||||
// ... but 1 still should be. | // ... but 1 still should be. | ||||
BOOST_CHECK(banman->IsBanned(addr1)); | BOOST_CHECK(banman->IsBanned(addr1)); | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
Misbehaving(dummyNode2.GetId(), 50, ""); | Misbehaving(dummyNode2.GetId(), 50, ""); | ||||
} | } | ||||
{ | { | ||||
LOCK2(cs_main, dummyNode2.cs_sendProcessing); | LOCK2(cs_main, dummyNode2.cs_sendProcessing); | ||||
peerLogic->SendMessages(config, &dummyNode2, interruptDummy); | BOOST_CHECK( | ||||
peerLogic->SendMessages(config, &dummyNode2, interruptDummy)); | |||||
} | } | ||||
BOOST_CHECK(banman->IsBanned(addr2)); | BOOST_CHECK(banman->IsBanned(addr2)); | ||||
bool dummy; | bool dummy; | ||||
peerLogic->FinalizeNode(config, dummyNode1.GetId(), dummy); | peerLogic->FinalizeNode(config, dummyNode1.GetId(), dummy); | ||||
peerLogic->FinalizeNode(config, dummyNode2.GetId(), dummy); | peerLogic->FinalizeNode(config, dummyNode2.GetId(), dummy); | ||||
} | } | ||||
Show All 19 Lines | BOOST_AUTO_TEST_CASE(DoS_banscore) { | ||||
dummyNode1.nVersion = 1; | dummyNode1.nVersion = 1; | ||||
dummyNode1.fSuccessfullyConnected = true; | dummyNode1.fSuccessfullyConnected = true; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
Misbehaving(dummyNode1.GetId(), 100, ""); | Misbehaving(dummyNode1.GetId(), 100, ""); | ||||
} | } | ||||
{ | { | ||||
LOCK2(cs_main, dummyNode1.cs_sendProcessing); | LOCK2(cs_main, dummyNode1.cs_sendProcessing); | ||||
peerLogic->SendMessages(config, &dummyNode1, interruptDummy); | BOOST_CHECK( | ||||
peerLogic->SendMessages(config, &dummyNode1, interruptDummy)); | |||||
} | } | ||||
BOOST_CHECK(!banman->IsBanned(addr1)); | BOOST_CHECK(!banman->IsBanned(addr1)); | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
Misbehaving(dummyNode1.GetId(), 10, ""); | Misbehaving(dummyNode1.GetId(), 10, ""); | ||||
} | } | ||||
{ | { | ||||
LOCK2(cs_main, dummyNode1.cs_sendProcessing); | LOCK2(cs_main, dummyNode1.cs_sendProcessing); | ||||
peerLogic->SendMessages(config, &dummyNode1, interruptDummy); | BOOST_CHECK( | ||||
peerLogic->SendMessages(config, &dummyNode1, interruptDummy)); | |||||
} | } | ||||
BOOST_CHECK(!banman->IsBanned(addr1)); | BOOST_CHECK(!banman->IsBanned(addr1)); | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
Misbehaving(dummyNode1.GetId(), 1, ""); | Misbehaving(dummyNode1.GetId(), 1, ""); | ||||
} | } | ||||
{ | { | ||||
LOCK2(cs_main, dummyNode1.cs_sendProcessing); | LOCK2(cs_main, dummyNode1.cs_sendProcessing); | ||||
peerLogic->SendMessages(config, &dummyNode1, interruptDummy); | BOOST_CHECK( | ||||
peerLogic->SendMessages(config, &dummyNode1, interruptDummy)); | |||||
} | } | ||||
BOOST_CHECK(banman->IsBanned(addr1)); | BOOST_CHECK(banman->IsBanned(addr1)); | ||||
gArgs.ForceSetArg("-banscore", std::to_string(DEFAULT_BANSCORE_THRESHOLD)); | gArgs.ForceSetArg("-banscore", std::to_string(DEFAULT_BANSCORE_THRESHOLD)); | ||||
bool dummy; | bool dummy; | ||||
peerLogic->FinalizeNode(config, dummyNode1.GetId(), dummy); | peerLogic->FinalizeNode(config, dummyNode1.GetId(), dummy); | ||||
} | } | ||||
Show All 22 Lines | BOOST_AUTO_TEST_CASE(DoS_bantime) { | ||||
dummyNode.fSuccessfullyConnected = true; | dummyNode.fSuccessfullyConnected = true; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
Misbehaving(dummyNode.GetId(), 100, ""); | Misbehaving(dummyNode.GetId(), 100, ""); | ||||
} | } | ||||
{ | { | ||||
LOCK2(cs_main, dummyNode.cs_sendProcessing); | LOCK2(cs_main, dummyNode.cs_sendProcessing); | ||||
peerLogic->SendMessages(config, &dummyNode, interruptDummy); | BOOST_CHECK( | ||||
peerLogic->SendMessages(config, &dummyNode, interruptDummy)); | |||||
} | } | ||||
BOOST_CHECK(banman->IsBanned(addr)); | BOOST_CHECK(banman->IsBanned(addr)); | ||||
bool dummy; | bool dummy; | ||||
peerLogic->FinalizeNode(config, dummyNode.GetId(), dummy); | peerLogic->FinalizeNode(config, dummyNode.GetId(), dummy); | ||||
} | } | ||||
static CTransactionRef RandomOrphan() { | static CTransactionRef RandomOrphan() { | ||||
std::map<uint256, COrphanTx>::iterator it; | std::map<uint256, COrphanTx>::iterator it; | ||||
LOCK2(cs_main, g_cs_orphans); | LOCK2(cs_main, g_cs_orphans); | ||||
it = mapOrphanTransactions.lower_bound(InsecureRand256()); | it = mapOrphanTransactions.lower_bound(InsecureRand256()); | ||||
if (it == mapOrphanTransactions.end()) { | if (it == mapOrphanTransactions.end()) { | ||||
it = mapOrphanTransactions.begin(); | it = mapOrphanTransactions.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); | ||||
FillableSigningProvider keystore; | FillableSigningProvider keystore; | ||||
keystore.AddKey(key); | BOOST_CHECK(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(TxId(InsecureRand256()), 0); | tx.vin[0].prevout = COutPoint(TxId(InsecureRand256()), 0); | ||||
tx.vin[0].scriptSig << OP_1; | tx.vin[0].scriptSig << OP_1; | ||||
tx.vout.resize(1); | tx.vout.resize(1); | ||||
Show All 10 Lines | for (int i = 0; i < 50; i++) { | ||||
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(PKHash(key.GetPubKey())); | GetScriptForDestination(PKHash(key.GetPubKey())); | ||||
SignSignature(keystore, *txPrev, tx, 0, SigHashType()); | BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, | ||||
SigHashType().withForkId())); | |||||
AddOrphanTx(MakeTransactionRef(tx), i); | 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(PKHash(key.GetPubKey())); | GetScriptForDestination(PKHash(key.GetPubKey())); | ||||
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()); | BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, | ||||
SigHashType().withForkId())); | |||||
// 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(!AddOrphanTx(MakeTransactionRef(tx), i)); | ||||
} | } | ||||
Show All 19 Lines |