From 3108aed0f210fe6cb698237c7eeac8715fb95e31 Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Wed, 29 Feb 2012 10:14:18 -0500 Subject: [PATCH] DoS fix for mapOrphanTransactions --- src/main.cpp | 25 ++++++++++++++++++++++++- src/main.h | 1 + 2 files changed, 25 insertions(+), 1 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 9f12829..8b11c2b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -159,13 +159,14 @@ void static ResendWalletTransactions() // mapOrphanTransactions // -void static AddOrphanTx(const CDataStream& vMsg) +void AddOrphanTx(const CDataStream& vMsg) { CTransaction tx; CDataStream(vMsg) >> tx; uint256 hash = tx.GetHash(); if (mapOrphanTransactions.count(hash)) return; + CDataStream* pvMsg = mapOrphanTransactions[hash] = new CDataStream(vMsg); BOOST_FOREACH(const CTxIn& txin, tx.vin) mapOrphanTransactionsByPrev.insert(make_pair(txin.prevout.hash, pvMsg)); @@ -193,6 +194,23 @@ void static EraseOrphanTx(uint256 hash) mapOrphanTransactions.erase(hash); } +int LimitOrphanTxSize(int nMaxOrphans) +{ + int nEvicted = 0; + while (mapOrphanTransactions.size() > nMaxOrphans) + { + // Evict a random orphan: + std::vector randbytes(32); + RAND_bytes(&randbytes[0], 32); + uint256 randomhash(randbytes); + map::iterator it = mapOrphanTransactions.lower_bound(randomhash); + if (it == mapOrphanTransactions.end()) + it = mapOrphanTransactions.begin(); + EraseOrphanTx(it->first); + ++nEvicted; + } + return nEvicted; +} @@ -2183,6 +2201,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) { printf("storing orphan tx %s\n", inv.hash.ToString().substr(0,10).c_str()); AddOrphanTx(vMsg); + + // DoS prevention: do not allow mapOrphanTransactions to grow unbounded + int nEvicted = LimitOrphanTxSize(MAX_ORPHAN_TRANSACTIONS); + if (nEvicted > 0) + printf("mapOrphan overflow, removed %d tx\n", nEvicted); } } diff --git a/src/main.h b/src/main.h index 25cf079..3e381b0 100644 --- a/src/main.h +++ b/src/main.h @@ -30,6 +30,7 @@ class CBlockIndex; static const unsigned int MAX_BLOCK_SIZE = 1000000; static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2; static const int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50; +static const int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100; static const int64 COIN = 100000000; static const int64 CENT = 1000000; static const int64 MIN_TX_FEE = 50000; -- 1.7.1