From ff9ecd8062feddcd6245c165747af6efc87e14cd Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Mon, 23 Nov 2015 01:54:23 +0000 Subject: [PATCH] Limit setAskFor and retire requested entries only when a getdata returns. The setAskFor duplicate elimination was too eager and removed entries when we still had no getdata response, allowing the peer to keep INVing and not responding. --- src/net.cpp | 4 ++-- src/net.h | 2 ++ src/net_processing.cpp | 5 ++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 715e0f4e8d53e0..e8c5bcbd51ba98 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2487,9 +2487,9 @@ CNode::~CNode() void CNode::AskFor(const CInv& inv) { - if (mapAskFor.size() > MAPASKFOR_MAX_SZ) + if (mapAskFor.size() > MAPASKFOR_MAX_SZ || setAskFor.size() > SETASKFOR_MAX_SZ) return; - // a peer may not occupy multiple positions in an inv's request queue + // a peer may not have multiple non-responded queue positions for a single inv item if (!setAskFor.insert(inv.hash).second) return; diff --git a/src/net.h b/src/net.h index 7478c27eb53c3e..ab959fc5ab1822 100644 --- a/src/net.h +++ b/src/net.h @@ -69,6 +69,8 @@ static const bool DEFAULT_UPNP = false; #endif /** The maximum number of entries in mapAskFor */ static const size_t MAPASKFOR_MAX_SZ = MAX_INV_SZ; +/** The maximum number of entries in setAskFor (larger due to getdata latency)*/ +static const size_t SETASKFOR_MAX_SZ = 2 * MAX_INV_SZ; /** The maximum number of peer connections to maintain. */ static const unsigned int DEFAULT_MAX_PEER_CONNECTIONS = 125; /** Disconnected peers are added to setOffsetDisconnectedPeers only if node has less than ENOUGH_CONNECTIONS */ diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 5879194edad2d9..ccbd57ee58dbcc 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1508,6 +1508,7 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR bool fMissingInputs = false; CValidationState state; + pfrom->setAskFor.erase(inv.hash); mapAlreadyAskedFor.erase(inv); if (ptx->ContainsZerocoins()) { @@ -2370,8 +2371,10 @@ bool SendMessages(CNode* pto, CConnman& connman, std::atomic& interruptMsg connman.PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData)); vGetData.clear(); } + } else { + //If we're not going to ask, don't expect a response. + pto->setAskFor.erase(inv.hash); } - pto->setAskFor.erase(inv.hash); pto->mapAskFor.erase(pto->mapAskFor.begin()); } if (!vGetData.empty())