Skip to content

Commit 03e9edb

Browse files
committed
llmq: Implement request limiting for QGETDATA/QDATA
1 parent aea5dd7 commit 03e9edb

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

src/llmq/quorums.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ class CQuorumDataRequest
107107
}
108108
};
109109

110+
static CCriticalSection cs_requests;
111+
static std::map<std::pair<uint256, bool>, CQuorumDataRequest> mapQuorumDataRequests;
112+
110113
CQuorum::~CQuorum()
111114
{
112115
// most likely the thread is already done
@@ -271,6 +274,17 @@ void CQuorumManager::UpdatedBlockTip(const CBlockIndex* pindexNew, bool fInitial
271274
for (auto& p : Params().GetConsensus().llmqs) {
272275
EnsureQuorumConnections(p.first, pindexNew);
273276
}
277+
278+
// Cleanup expired data requests
279+
LOCK(cs_requests);
280+
auto it = mapQuorumDataRequests.begin();
281+
while (it != mapQuorumDataRequests.end()) {
282+
if (it->second.IsExpired()) {
283+
it = mapQuorumDataRequests.erase(it);
284+
} else {
285+
++it;
286+
}
287+
}
274288
}
275289

276290
void CQuorumManager::EnsureQuorumConnections(Consensus::LLMQType llmqType, const CBlockIndex* pindexNew)
@@ -517,6 +531,19 @@ void CQuorumManager::ProcessMessage(CNode* pFrom, const std::string& strCommand,
517531
g_connman->PushMessage(pFrom, msgMaker.Make(NetMsgType::QDATA, ssResponse));
518532
};
519533

534+
{
535+
LOCK(cs_requests);
536+
auto key = std::make_pair(pFrom->verifiedProRegTxHash, false);
537+
auto it = mapQuorumDataRequests.find(key);
538+
if (it == mapQuorumDataRequests.end()) {
539+
it = mapQuorumDataRequests.emplace(key, request).first;
540+
} else if(it->second.IsExpired()) {
541+
it->second = request;
542+
} else {
543+
error("Request limit exceeded", true, 25);
544+
}
545+
}
546+
520547
if (Params().GetConsensus().llmqs.count(request.GetLLMQType()) == 0) {
521548
sendQDATA(llmq::QuorumData::QUORUM_TYPE_INVALID);
522549
return;
@@ -580,6 +607,29 @@ void CQuorumManager::ProcessMessage(CNode* pFrom, const std::string& strCommand,
580607
vRecv >> request;
581608
vRecv >> nError;
582609

610+
{
611+
LOCK(cs_requests);
612+
613+
auto it = mapQuorumDataRequests.find(std::make_pair(pFrom->verifiedProRegTxHash, true));
614+
615+
if (it == mapQuorumDataRequests.end()) {
616+
error("Not requested");
617+
return;
618+
}
619+
620+
if (it->second.IsProcessed()) {
621+
error("Already received");
622+
return;
623+
}
624+
625+
if (request != it->second) {
626+
error("Not like requested");
627+
return;
628+
}
629+
630+
it->second.SetProcessed();
631+
}
632+
583633
const CBlockIndex* pQuorumIndex = LookupBlockIndex(request.GetQuorumHash());
584634
if (pQuorumIndex == nullptr) {
585635
error("Quorum block not found");

0 commit comments

Comments
 (0)