From 56f165bdc1ad3940fee2e345aa2706f502866c67 Mon Sep 17 00:00:00 2001 From: kazcw Date: Wed, 16 Jul 2014 14:31:41 -0700 Subject: [PATCH] prevent peer flooding request queue for an inv mapAlreadyAskedFor does not keep track of which peer has a request queued for a particular tx. As a result, a peer can blind a node to a tx indefinitely by sending many invs for the same tx, and then never replying to getdatas for it. Each inv received will be placed 2 minutes farther back in mapAlreadyAskedFor, so a short message containing 10 invs would render that tx unavailable for 20 minutes. This is fixed by disallowing a peer from having more than one entry for a particular inv in mapAlreadyAskedFor at a time. --- src/main.cpp | 1 + src/net.cpp | 4 ++++ src/net.h | 1 + 3 files changed, 6 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 082456af..88686df6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5452,6 +5452,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) vGetData.clear(); } } + pto->setAskFor.erase(inv.hash); pto->mapAskFor.erase(pto->mapAskFor.begin()); } if (!vGetData.empty()) diff --git a/src/net.cpp b/src/net.cpp index 04e48ac6..710e6167 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2180,6 +2180,10 @@ void CNode::AskFor(const CInv& inv) { if (mapAskFor.size() > MAPASKFOR_MAX_SZ) return; + // a peer may not occupy multiple positions in an inv's request queue + if (!setAskFor.insert(inv.hash).second) + return; + // We're using mapAskFor as a priority queue, // the key is the earliest time the request can be sent int64_t nRequestTime; diff --git a/src/net.h b/src/net.h index 66f733e0..bc6ab291 100644 --- a/src/net.h +++ b/src/net.h @@ -310,6 +310,7 @@ public: mruset setInventoryKnown; std::vector vInventoryToSend; CCriticalSection cs_inventory; + std::set setAskFor; std::multimap mapAskFor; // Ping time measurement: