Skip to content

Commit

Permalink
Avoid using ordered maps in LLMQ signing code (#2708)
Browse files Browse the repository at this point in the history
* Implement and use SigShareMap instead of ordered map with helper methods

The old implementation was relying on the maps being ordered, which allowed
us to grab all sig shares for the same signHash by doing range queries on
the map. This has the disadvantage of being unnecessarily slow when the
maps get larger. Using an unordered map would be the naive solution, but
then it's not possible to query by range anymore.

The solution now is to have a specialized map "SigShareMap" which is
indexed by "SigShareKey". It's internally just an unordered map, indexed by
the sign hash and another unordered map for the value, indexed by the
quorum member index.

* Only use unordered maps/sets in CSigSharesManager

These are faster when maps/sets get larger.

* Use unorderes sets/maps in CSigningManager
  • Loading branch information
codablock authored and UdjinM6 committed Feb 17, 2019
1 parent 7a192e2 commit 9f58690
Show file tree
Hide file tree
Showing 4 changed files with 298 additions and 154 deletions.
13 changes: 7 additions & 6 deletions src/llmq/quorums_signing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include <algorithm>
#include <limits>
#include <unordered_set>

namespace llmq
{
Expand Down Expand Up @@ -357,16 +358,16 @@ bool CSigningManager::PreVerifyRecoveredSig(NodeId nodeId, const CRecoveredSig&

void CSigningManager::CollectPendingRecoveredSigsToVerify(
size_t maxUniqueSessions,
std::map<NodeId, std::list<CRecoveredSig>>& retSigShares,
std::map<std::pair<Consensus::LLMQType, uint256>, CQuorumCPtr>& retQuorums)
std::unordered_map<NodeId, std::list<CRecoveredSig>>& retSigShares,
std::unordered_map<std::pair<Consensus::LLMQType, uint256>, CQuorumCPtr>& retQuorums)
{
{
LOCK(cs);
if (pendingRecoveredSigs.empty()) {
return;
}

std::set<std::pair<NodeId, uint256>> uniqueSignHashes;
std::unordered_set<std::pair<NodeId, uint256>> uniqueSignHashes;
CLLMQUtils::IterateNodesRandom(pendingRecoveredSigs, [&]() {
return uniqueSignHashes.size() < maxUniqueSessions;
}, [&](NodeId nodeId, std::list<CRecoveredSig>& ns) {
Expand Down Expand Up @@ -423,8 +424,8 @@ void CSigningManager::CollectPendingRecoveredSigsToVerify(

bool CSigningManager::ProcessPendingRecoveredSigs(CConnman& connman)
{
std::map<NodeId, std::list<CRecoveredSig>> recSigsByNode;
std::map<std::pair<Consensus::LLMQType, uint256>, CQuorumCPtr> quorums;
std::unordered_map<NodeId, std::list<CRecoveredSig>> recSigsByNode;
std::unordered_map<std::pair<Consensus::LLMQType, uint256>, CQuorumCPtr> quorums;

CollectPendingRecoveredSigsToVerify(32, recSigsByNode, quorums);
if (recSigsByNode.empty()) {
Expand Down Expand Up @@ -453,7 +454,7 @@ bool CSigningManager::ProcessPendingRecoveredSigs(CConnman& connman)

LogPrint("llmq", "CSigningManager::%s -- verified recovered sig(s). count=%d, vt=%d, nodes=%d\n", __func__, verifyCount, verifyTimer.count(), recSigsByNode.size());

std::set<uint256> processed;
std::unordered_set<uint256> processed;
for (auto& p : recSigsByNode) {
NodeId nodeId = p.first;
auto& v = p.second;
Expand Down
4 changes: 2 additions & 2 deletions src/llmq/quorums_signing.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ class CSigningManager
CRecoveredSigsDb db;

// Incoming and not verified yet
std::map<NodeId, std::list<CRecoveredSig>> pendingRecoveredSigs;
std::unordered_map<NodeId, std::list<CRecoveredSig>> pendingRecoveredSigs;

// must be protected by cs
FastRandomContext rnd;
Expand All @@ -156,7 +156,7 @@ class CSigningManager
void ProcessMessageRecoveredSig(CNode* pfrom, const CRecoveredSig& recoveredSig, CConnman& connman);
bool PreVerifyRecoveredSig(NodeId nodeId, const CRecoveredSig& recoveredSig, bool& retBan);

void CollectPendingRecoveredSigsToVerify(size_t maxUniqueSessions, std::map<NodeId, std::list<CRecoveredSig>>& retSigShares, std::map<std::pair<Consensus::LLMQType, uint256>, CQuorumCPtr>& retQuorums);
void CollectPendingRecoveredSigsToVerify(size_t maxUniqueSessions, std::unordered_map<NodeId, std::list<CRecoveredSig>>& retSigShares, std::unordered_map<std::pair<Consensus::LLMQType, uint256>, CQuorumCPtr>& retQuorums);
bool ProcessPendingRecoveredSigs(CConnman& connman); // called from the worker thread of CSigSharesManager
void ProcessRecoveredSig(NodeId nodeId, const CRecoveredSig& recoveredSig, const CQuorumCPtr& quorum, CConnman& connman);
void Cleanup(); // called from the worker thread of CSigSharesManager
Expand Down
Loading

0 comments on commit 9f58690

Please sign in to comment.