Changeset View
Changeset View
Standalone View
Standalone View
src/test/denialofservice_tests.cpp
Show First 20 Lines • Show All 328 Lines • ▼ Show 20 Lines | peerLogic->Misbehaving(dummyNode.GetId(), DISCOURAGEMENT_THRESHOLD, | ||||
BOOST_CHECK(peerLogic->SendMessages(config, &dummyNode)); | BOOST_CHECK(peerLogic->SendMessages(config, &dummyNode)); | ||||
} | } | ||||
BOOST_CHECK(banman->IsDiscouraged(addr)); | BOOST_CHECK(banman->IsDiscouraged(addr)); | ||||
bool dummy; | bool dummy; | ||||
peerLogic->FinalizeNode(config, dummyNode, dummy); | peerLogic->FinalizeNode(config, dummyNode, dummy); | ||||
} | } | ||||
static CTransactionRef RandomOrphan() EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans) { | class TxOrphanageTest : public TxOrphanage { | ||||
public: | |||||
inline size_t CountOrphans() const EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans) { | |||||
return mapOrphanTransactions.size(); | |||||
} | |||||
CTransactionRef RandomOrphan() EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans) { | |||||
std::map<TxId, COrphanTx>::iterator it; | std::map<TxId, COrphanTx>::iterator it; | ||||
it = mapOrphanTransactions.lower_bound(TxId{InsecureRand256()}); | it = mapOrphanTransactions.lower_bound(TxId{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) { | ||||
TxOrphanageTest orphanage; | |||||
CKey key; | CKey key; | ||||
key.MakeNewKey(true); | key.MakeNewKey(true); | ||||
FillableSigningProvider keystore; | FillableSigningProvider keystore; | ||||
BOOST_CHECK(keystore.AddKey(key)); | BOOST_CHECK(keystore.AddKey(key)); | ||||
LOCK(g_cs_orphans); | LOCK(g_cs_orphans); | ||||
// 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); | ||||
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())); | ||||
OrphanageAddTx(MakeTransactionRef(tx), i); | orphanage.AddTx(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 = orphanage.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(PKHash(key.GetPubKey())); | GetScriptForDestination(PKHash(key.GetPubKey())); | ||||
BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, | BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, | ||||
SigHashType().withForkId())); | SigHashType().withForkId())); | ||||
OrphanageAddTx(MakeTransactionRef(tx), i); | orphanage.AddTx(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 = orphanage.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); | ||||
} | } | ||||
BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, | BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, | ||||
SigHashType().withForkId())); | 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(!OrphanageAddTx(MakeTransactionRef(tx), i)); | BOOST_CHECK(!orphanage.AddTx(MakeTransactionRef(tx), i)); | ||||
} | } | ||||
// Test EraseOrphansFor: | // Test EraseOrphansFor: | ||||
for (NodeId i = 0; i < 3; i++) { | for (NodeId i = 0; i < 3; i++) { | ||||
size_t sizeBefore = mapOrphanTransactions.size(); | size_t sizeBefore = orphanage.CountOrphans(); | ||||
EraseOrphansFor(i); | orphanage.EraseForPeer(i); | ||||
BOOST_CHECK(mapOrphanTransactions.size() < sizeBefore); | BOOST_CHECK(orphanage.CountOrphans() < sizeBefore); | ||||
} | } | ||||
// Test LimitOrphanTxSize() function: | // Test LimitOrphanTxSize() function: | ||||
LimitOrphanTxSize(40); | orphanage.LimitOrphans(40); | ||||
BOOST_CHECK(mapOrphanTransactions.size() <= 40); | BOOST_CHECK(orphanage.CountOrphans() <= 40); | ||||
LimitOrphanTxSize(10); | orphanage.LimitOrphans(10); | ||||
BOOST_CHECK(mapOrphanTransactions.size() <= 10); | BOOST_CHECK(orphanage.CountOrphans() <= 10); | ||||
LimitOrphanTxSize(0); | orphanage.LimitOrphans(0); | ||||
BOOST_CHECK(mapOrphanTransactions.empty()); | BOOST_CHECK(orphanage.CountOrphans() == 0); | ||||
} | } | ||||
BOOST_AUTO_TEST_SUITE_END() | BOOST_AUTO_TEST_SUITE_END() |