aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGavin Andresen <gavinandresen@gmail.com>2012-02-29 10:14:18 -0500
committerLuke Dashjr <luke-jr+git@utopios.org>2012-03-02 13:04:39 -0500
commit3108aed0f210fe6cb698237c7eeac8715fb95e31 (patch)
treeb9a19d39e0408dd6500dde98b78b30c740259db0
parentfeb3c15335d5279931c1e0f713400fb616459d0b (diff)
downloadbitcoin-3108aed0f210fe6cb698237c7eeac8715fb95e31.tar.xz
DoS fix for mapOrphanTransactions
-rw-r--r--src/main.cpp25
-rw-r--r--src/main.h1
2 files changed, 25 insertions, 1 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 9f12829042..8b11c2bbf0 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<unsigned char> randbytes(32);
+ RAND_bytes(&randbytes[0], 32);
+ uint256 randomhash(randbytes);
+ map<uint256, CDataStream*>::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 25cf079013..3e381b060b 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;