From 677c0040cd01260c81848042ced58befd984d60d Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Tue, 26 Feb 2019 07:20:47 +0100 Subject: [PATCH 1/5] Add in-memory cache to CQuorumBlockProcessor::HasMinedCommitment --- src/llmq/quorums_blockprocessor.cpp | 24 +++++++++++++++++++++++- src/llmq/quorums_blockprocessor.h | 4 ++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/llmq/quorums_blockprocessor.cpp b/src/llmq/quorums_blockprocessor.cpp index 49f4425b2..82861dab3 100644 --- a/src/llmq/quorums_blockprocessor.cpp +++ b/src/llmq/quorums_blockprocessor.cpp @@ -199,6 +199,11 @@ bool CQuorumBlockProcessor::ProcessCommitment(const CBlockIndex* pindex, const C evoDb.Write(std::make_pair(DB_FIRST_MINED_COMMITMENT, (uint8_t)params.type), quorumHash); } + { + LOCK(minableCommitmentsCs); + hasMinedCommitmentCache.erase(std::make_pair(params.type, quorumHash)); + } + LogPrintf("CQuorumBlockProcessor::%s -- processed commitment from block. type=%d, quorumHash=%s, signers=%s, validMembers=%d, quorumPublicKey=%s\n", __func__, qc.llmqType, quorumHash.ToString(), qc.CountSigners(), qc.CountValidMembers(), qc.quorumPublicKey.ToString()); @@ -222,6 +227,10 @@ bool CQuorumBlockProcessor::UndoBlock(const CBlock& block, const CBlockIndex* pi } evoDb.Erase(std::make_pair(DB_MINED_COMMITMENT, std::make_pair(qc.llmqType, qc.quorumHash))); + { + LOCK(minableCommitmentsCs); + hasMinedCommitmentCache.erase(std::make_pair((Consensus::LLMQType)qc.llmqType, qc.quorumHash)); + } // if a reorg happened, we should allow to mine this commitment later AddMinableCommitment(qc); @@ -309,8 +318,21 @@ uint256 CQuorumBlockProcessor::GetQuorumBlockHash(Consensus::LLMQType llmqType, bool CQuorumBlockProcessor::HasMinedCommitment(Consensus::LLMQType llmqType, const uint256& quorumHash) { + auto cacheKey = std::make_pair(llmqType, quorumHash); + { + LOCK(minableCommitmentsCs); + auto cacheIt = hasMinedCommitmentCache.find(cacheKey); + if (cacheIt != hasMinedCommitmentCache.end()) { + return cacheIt->second; + } + } + auto key = std::make_pair(DB_MINED_COMMITMENT, std::make_pair((uint8_t)llmqType, quorumHash)); - return evoDb.Exists(key); + bool ret = evoDb.Exists(key); + + LOCK(minableCommitmentsCs); + hasMinedCommitmentCache.emplace(cacheKey, ret); + return ret; } bool CQuorumBlockProcessor::GetMinedCommitment(Consensus::LLMQType llmqType, const uint256& quorumHash, CFinalCommitment& ret) diff --git a/src/llmq/quorums_blockprocessor.h b/src/llmq/quorums_blockprocessor.h index 0afd2a8f0..330338d44 100644 --- a/src/llmq/quorums_blockprocessor.h +++ b/src/llmq/quorums_blockprocessor.h @@ -6,12 +6,14 @@ #define DASH_QUORUMS_BLOCKPROCESSOR_H #include "llmq/quorums_commitment.h" +#include "llmq/quorums_utils.h" #include "consensus/params.h" #include "primitives/transaction.h" #include "sync.h" #include +#include class CNode; class CConnman; @@ -29,6 +31,8 @@ private: std::map, uint256> minableCommitmentsByQuorum; std::map minableCommitments; + std::unordered_map, bool> hasMinedCommitmentCache; + public: CQuorumBlockProcessor(CEvoDB& _evoDb) : evoDb(_evoDb) {} From e83e32b956544808184f1b3f3eb15aa94a547b88 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Tue, 26 Feb 2019 07:22:35 +0100 Subject: [PATCH 2/5] Add in-memory cache for CRecoveredSigsDb::HasRecoveredSigForHash --- src/llmq/quorums_signing.cpp | 20 +++++++++++++++++++- src/llmq/quorums_signing.h | 1 + 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/llmq/quorums_signing.cpp b/src/llmq/quorums_signing.cpp index acd7fef16..65ec455cd 100644 --- a/src/llmq/quorums_signing.cpp +++ b/src/llmq/quorums_signing.cpp @@ -81,8 +81,23 @@ bool CRecoveredSigsDb::HasRecoveredSigForSession(const uint256& signHash) bool CRecoveredSigsDb::HasRecoveredSigForHash(const uint256& hash) { + int64_t t = GetTimeMillis(); + + { + LOCK(cs); + auto it = hasSigForHashCache.find(hash); + if (it != hasSigForHashCache.end()) { + it->second.second = t; + return it->second.first; + } + } + auto k = std::make_tuple('h', hash); - return db.Exists(k); + bool ret = db.Exists(k); + + LOCK(cs); + hasSigForHashCache.emplace(hash, std::make_pair(ret, t)); + return ret; } bool CRecoveredSigsDb::ReadRecoveredSig(Consensus::LLMQType llmqType, const uint256& id, CRecoveredSig& ret) @@ -154,6 +169,7 @@ void CRecoveredSigsDb::WriteRecoveredSig(const llmq::CRecoveredSig& recSig) LOCK(cs); hasSigForIdCache[std::make_pair((Consensus::LLMQType)recSig.llmqType, recSig.id)] = std::make_pair(true, t); hasSigForSessionCache[signHash] = std::make_pair(true, t); + hasSigForHashCache[recSig.GetHash()] = std::make_pair(true, t); } } @@ -239,10 +255,12 @@ void CRecoveredSigsDb::CleanupOldRecoveredSigs(int64_t maxAge) hasSigForIdCache.erase(std::make_pair((Consensus::LLMQType)recSig.llmqType, recSig.id)); hasSigForSessionCache.erase(signHash); + hasSigForHashCache.erase(recSig.GetHash()); } TruncateCacheMap(hasSigForIdCache, MAX_CACHE_SIZE, MAX_CACHE_TRUNCATE_THRESHOLD); TruncateCacheMap(hasSigForSessionCache, MAX_CACHE_SIZE, MAX_CACHE_TRUNCATE_THRESHOLD); + TruncateCacheMap(hasSigForHashCache, MAX_CACHE_SIZE, MAX_CACHE_TRUNCATE_THRESHOLD); } for (auto& e : toDelete2) { diff --git a/src/llmq/quorums_signing.h b/src/llmq/quorums_signing.h index 03bfb2ad5..e04dc3481 100644 --- a/src/llmq/quorums_signing.h +++ b/src/llmq/quorums_signing.h @@ -88,6 +88,7 @@ private: CCriticalSection cs; std::unordered_map, std::pair> hasSigForIdCache; std::unordered_map> hasSigForSessionCache; + std::unordered_map> hasSigForHashCache; public: CRecoveredSigsDb(bool fMemory); From c52e8402c063def4b1ea5f26f41c014fcbe3f534 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Tue, 26 Feb 2019 07:50:19 +0100 Subject: [PATCH 3/5] Remove now obsolete TODO comment above CRecoveredSigsDb --- src/llmq/quorums_signing.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/llmq/quorums_signing.h b/src/llmq/quorums_signing.h index e04dc3481..9e53ab186 100644 --- a/src/llmq/quorums_signing.h +++ b/src/llmq/quorums_signing.h @@ -76,7 +76,6 @@ public: } }; -// TODO implement caching to speed things up class CRecoveredSigsDb { static const size_t MAX_CACHE_SIZE = 30000; From b5462f52460e7c4f982dec8396e46b5928c638a3 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Tue, 26 Feb 2019 14:13:19 +0100 Subject: [PATCH 4/5] Implement std::unordered_map/set compatible hasher classes for salted hashes Allows convenient salted hashing with unordered maps and sets. Useful when there is a risk of unbalanced hash buckets slowing things down, e.g. when externally supplied hashes are used as keys into a map. --- src/Makefile.am | 2 ++ src/saltedhasher.cpp | 12 +++++++ src/saltedhasher.h | 75 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 src/saltedhasher.cpp create mode 100644 src/saltedhasher.h diff --git a/src/Makefile.am b/src/Makefile.am index b295405a5..04a5efa3a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -201,6 +201,7 @@ BITCOIN_CORE_H = \ rpc/protocol.h \ rpc/server.h \ rpc/register.h \ + saltedhasher.h \ scheduler.h \ script/sigcache.h \ script/sign.h \ @@ -463,6 +464,7 @@ libdash_common_a_SOURCES = \ netaddress.cpp \ netbase.cpp \ protocol.cpp \ + saltedhasher.cpp \ scheduler.cpp \ script/sign.cpp \ script/standard.cpp \ diff --git a/src/saltedhasher.cpp b/src/saltedhasher.cpp new file mode 100644 index 000000000..ec3c819f2 --- /dev/null +++ b/src/saltedhasher.cpp @@ -0,0 +1,12 @@ +// Copyright (c) 2019 The Dash Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "saltedhasher.h" +#include "random.h" + +#include + +SaltedHasherBase::SaltedHasherBase() : k0(GetRand(std::numeric_limits::max())), k1(GetRand(std::numeric_limits::max())) {} + +SaltedHasherBase StaticSaltedHasher::s; diff --git a/src/saltedhasher.h b/src/saltedhasher.h new file mode 100644 index 000000000..ffd5cd638 --- /dev/null +++ b/src/saltedhasher.h @@ -0,0 +1,75 @@ +// Copyright (c) 2019 The Dash Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef SALTEDHASHER_H +#define SALTEDHASHER_H + +#include "hash.h" +#include "uint256.h" + +/** Helper classes for std::unordered_map and std::unordered_set hashing */ + +template struct SaltedHasherImpl; + +template +struct SaltedHasherImpl> +{ + static std::size_t CalcHash(const std::pair& v, uint64_t k0, uint64_t k1) + { + return SipHashUint256Extra(k0, k1, v.first, (uint32_t) v.second); + } +}; + +template +struct SaltedHasherImpl> +{ + static std::size_t CalcHash(const std::pair& v, uint64_t k0, uint64_t k1) + { + return SipHashUint256Extra(k0, k1, v.second, (uint32_t) v.first); + } +}; + +template<> +struct SaltedHasherImpl +{ + static std::size_t CalcHash(const uint256& v, uint64_t k0, uint64_t k1) + { + return SipHashUint256(k0, k1, v); + } +}; + +struct SaltedHasherBase +{ + /** Salt */ + const uint64_t k0, k1; + + SaltedHasherBase(); +}; + +/* Allows each instance of unordered maps/sest to have their own salt */ +template +struct SaltedHasher +{ + S s; + std::size_t operator()(const T& v) const + { + return SaltedHasherImpl::CalcHash(v, s.k0, s.k1); + } +}; + +/* Allows to use a static salt for all instances. The salt is a random value set at startup + * (through static initialization) + */ +struct StaticSaltedHasher +{ + static SaltedHasherBase s; + + template + std::size_t operator()(const T& v) const + { + return SaltedHasherImpl::CalcHash(v, s.k0, s.k1); + } +}; + +#endif//SALTEDHASHER_H From 9b4285b1c87796f0da2ab912a1ac4371449f262c Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Tue, 26 Feb 2019 07:19:58 +0100 Subject: [PATCH 5/5] Use salted hashing for keys for unordered maps/sets in LLMQ code We must watch out to not blindly use externally provided keys in unordered sets/maps, as attackers might find ways to cause unbalanced hash buckets causing performance degradation. --- src/llmq/quorums_blockprocessor.h | 3 +- src/llmq/quorums_signing.cpp | 14 ++++----- src/llmq/quorums_signing.h | 22 +++++--------- src/llmq/quorums_signing_shares.cpp | 39 ++++++++++++------------ src/llmq/quorums_signing_shares.h | 47 +++++++++-------------------- 5 files changed, 51 insertions(+), 74 deletions(-) diff --git a/src/llmq/quorums_blockprocessor.h b/src/llmq/quorums_blockprocessor.h index 330338d44..f630bf0d6 100644 --- a/src/llmq/quorums_blockprocessor.h +++ b/src/llmq/quorums_blockprocessor.h @@ -10,6 +10,7 @@ #include "consensus/params.h" #include "primitives/transaction.h" +#include "saltedhasher.h" #include "sync.h" #include @@ -31,7 +32,7 @@ private: std::map, uint256> minableCommitmentsByQuorum; std::map minableCommitments; - std::unordered_map, bool> hasMinedCommitmentCache; + std::unordered_map, bool, StaticSaltedHasher> hasMinedCommitmentCache; public: CQuorumBlockProcessor(CEvoDB& _evoDb) : evoDb(_evoDb) {} diff --git a/src/llmq/quorums_signing.cpp b/src/llmq/quorums_signing.cpp index 65ec455cd..cf08178ef 100644 --- a/src/llmq/quorums_signing.cpp +++ b/src/llmq/quorums_signing.cpp @@ -173,10 +173,10 @@ void CRecoveredSigsDb::WriteRecoveredSig(const llmq::CRecoveredSig& recSig) } } -template -static void TruncateCacheMap(std::unordered_map>& m, size_t maxSize, size_t truncateThreshold) +template +static void TruncateCacheMap(std::unordered_map, H>& m, size_t maxSize, size_t truncateThreshold) { - typedef typename std::unordered_map> Map; + typedef typename std::unordered_map, H> Map; typedef typename Map::iterator Iterator; if (m.size() <= truncateThreshold) { @@ -377,7 +377,7 @@ bool CSigningManager::PreVerifyRecoveredSig(NodeId nodeId, const CRecoveredSig& void CSigningManager::CollectPendingRecoveredSigsToVerify( size_t maxUniqueSessions, std::unordered_map>& retSigShares, - std::unordered_map, CQuorumCPtr>& retQuorums) + std::unordered_map, CQuorumCPtr, StaticSaltedHasher>& retQuorums) { { LOCK(cs); @@ -385,7 +385,7 @@ void CSigningManager::CollectPendingRecoveredSigsToVerify( return; } - std::unordered_set> uniqueSignHashes; + std::unordered_set, StaticSaltedHasher> uniqueSignHashes; CLLMQUtils::IterateNodesRandom(pendingRecoveredSigs, [&]() { return uniqueSignHashes.size() < maxUniqueSessions; }, [&](NodeId nodeId, std::list& ns) { @@ -443,7 +443,7 @@ void CSigningManager::CollectPendingRecoveredSigsToVerify( bool CSigningManager::ProcessPendingRecoveredSigs(CConnman& connman) { std::unordered_map> recSigsByNode; - std::unordered_map, CQuorumCPtr> quorums; + std::unordered_map, CQuorumCPtr, StaticSaltedHasher> quorums; CollectPendingRecoveredSigsToVerify(32, recSigsByNode, quorums); if (recSigsByNode.empty()) { @@ -472,7 +472,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::unordered_set processed; + std::unordered_set processed; for (auto& p : recSigsByNode) { NodeId nodeId = p.first; auto& v = p.second; diff --git a/src/llmq/quorums_signing.h b/src/llmq/quorums_signing.h index 9e53ab186..1d0024351 100644 --- a/src/llmq/quorums_signing.h +++ b/src/llmq/quorums_signing.h @@ -9,20 +9,10 @@ #include "net.h" #include "chainparams.h" +#include "saltedhasher.h" #include -namespace std { - template <> - struct hash> - { - std::size_t operator()(const std::pair& k) const - { - return (std::size_t)((k.first + 1) * k.second.GetCheapHash()); - } - }; -} - namespace llmq { @@ -85,9 +75,9 @@ private: CDBWrapper db; CCriticalSection cs; - std::unordered_map, std::pair> hasSigForIdCache; - std::unordered_map> hasSigForSessionCache; - std::unordered_map> hasSigForHashCache; + std::unordered_map, std::pair, StaticSaltedHasher> hasSigForIdCache; + std::unordered_map, StaticSaltedHasher> hasSigForSessionCache; + std::unordered_map, StaticSaltedHasher> hasSigForHashCache; public: CRecoveredSigsDb(bool fMemory); @@ -156,7 +146,9 @@ private: void ProcessMessageRecoveredSig(CNode* pfrom, const CRecoveredSig& recoveredSig, CConnman& connman); bool PreVerifyRecoveredSig(NodeId nodeId, const CRecoveredSig& recoveredSig, bool& retBan); - void CollectPendingRecoveredSigsToVerify(size_t maxUniqueSessions, std::unordered_map>& retSigShares, std::unordered_map, CQuorumCPtr>& retQuorums); + void CollectPendingRecoveredSigsToVerify(size_t maxUniqueSessions, + std::unordered_map>& retSigShares, + std::unordered_map, CQuorumCPtr, StaticSaltedHasher>& 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 diff --git a/src/llmq/quorums_signing_shares.cpp b/src/llmq/quorums_signing_shares.cpp index b11bf3e20..36315de56 100644 --- a/src/llmq/quorums_signing_shares.cpp +++ b/src/llmq/quorums_signing_shares.cpp @@ -386,7 +386,7 @@ bool CSigSharesManager::PreVerifyBatchedSigShares(NodeId nodeId, const CBatchedS void CSigSharesManager::CollectPendingSigSharesToVerify( size_t maxUniqueSessions, std::unordered_map>& retSigShares, - std::unordered_map, CQuorumCPtr>& retQuorums) + std::unordered_map, CQuorumCPtr, StaticSaltedHasher>& retQuorums) { { LOCK(cs); @@ -400,7 +400,7 @@ void CSigSharesManager::CollectPendingSigSharesToVerify( // invalid, making batch verification fail and revert to per-share verification, which in turn would slow down // the whole verification process - std::unordered_set> uniqueSignHashes; + std::unordered_set, StaticSaltedHasher> uniqueSignHashes; CLLMQUtils::IterateNodesRandom(nodeStates, [&]() { return uniqueSignHashes.size() < maxUniqueSessions; }, [&](NodeId nodeId, CSigSharesNodeState& ns) { @@ -448,7 +448,7 @@ void CSigSharesManager::CollectPendingSigSharesToVerify( bool CSigSharesManager::ProcessPendingSigShares(CConnman& connman) { std::unordered_map> sigSharesByNodes; - std::unordered_map, CQuorumCPtr> quorums; + std::unordered_map, CQuorumCPtr, StaticSaltedHasher> quorums; CollectPendingSigSharesToVerify(32, sigSharesByNodes, quorums); if (sigSharesByNodes.empty()) { @@ -517,7 +517,10 @@ bool CSigSharesManager::ProcessPendingSigShares(CConnman& connman) } // It's ensured that no duplicates are passed to this method -void CSigSharesManager::ProcessPendingSigSharesFromNode(NodeId nodeId, const std::vector& sigShares, const std::unordered_map, CQuorumCPtr>& quorums, CConnman& connman) +void CSigSharesManager::ProcessPendingSigSharesFromNode(NodeId nodeId, + const std::vector& sigShares, + const std::unordered_map, CQuorumCPtr, StaticSaltedHasher>& quorums, + CConnman& connman) { auto& nodeState = nodeStates[nodeId]; @@ -668,11 +671,9 @@ void CSigSharesManager::TryRecoverSig(const CQuorumCPtr& quorum, const uint256& } // cs must be held -void CSigSharesManager::CollectSigSharesToRequest(std::unordered_map>& sigSharesToRequest) +void CSigSharesManager::CollectSigSharesToRequest(std::unordered_map>& sigSharesToRequest) { int64_t now = GetTimeMillis(); - std::unordered_map> nodesBySigShares; - const size_t maxRequestsForNode = 32; // avoid requesting from same nodes all the time @@ -703,7 +704,7 @@ void CSigSharesManager::CollectSigSharesToRequest(std::unordered_map* invMap = nullptr; + decltype(sigSharesToRequest.begin()->second)* invMap = nullptr; for (auto& p2 : nodeState.sessions) { auto& signHash = p2.first; @@ -764,7 +765,7 @@ void CSigSharesManager::CollectSigSharesToRequest(std::unordered_map>& sigSharesToSend) +void CSigSharesManager::CollectSigSharesToSend(std::unordered_map>& sigSharesToSend) { for (auto& p : nodeStates) { auto nodeId = p.first; @@ -774,7 +775,7 @@ void CSigSharesManager::CollectSigSharesToSend(std::unordered_map* sigSharesToSend2 = nullptr; + decltype(sigSharesToSend.begin()->second)* sigSharesToSend2 = nullptr; for (auto& p2 : nodeState.sessions) { auto& signHash = p2.first; @@ -821,9 +822,9 @@ void CSigSharesManager::CollectSigSharesToSend(std::unordered_map>& sigSharesToAnnounce) +void CSigSharesManager::CollectSigSharesToAnnounce(std::unordered_map>& sigSharesToAnnounce) { - std::unordered_set> quorumNodesPrepared; + std::unordered_set, StaticSaltedHasher> quorumNodesPrepared; this->sigSharesToAnnounce.ForEach([&](const SigShareKey& sigShareKey, bool) { auto& signHash = sigShareKey.first; @@ -890,9 +891,9 @@ bool CSigSharesManager::SendMessages() nodesByAddress.emplace(pnode->addr, pnode->id); }); - std::unordered_map> sigSharesToRequest; - std::unordered_map> sigSharesToSend; - std::unordered_map> sigSharesToAnnounce; + std::unordered_map> sigSharesToRequest; + std::unordered_map> sigSharesToSend; + std::unordered_map> sigSharesToAnnounce; { LOCK(cs); @@ -956,13 +957,13 @@ void CSigSharesManager::Cleanup() return; } - std::unordered_set> quorumsToCheck; + std::unordered_set, StaticSaltedHasher> quorumsToCheck; { LOCK(cs); // Remove sessions which were succesfully recovered - std::unordered_set doneSessions; + std::unordered_set doneSessions; sigShares.ForEach([&](const SigShareKey& k, const CSigShare& sigShare) { if (doneSessions.count(sigShare.GetSignHash())) { return; @@ -976,7 +977,7 @@ void CSigSharesManager::Cleanup() } // Remove sessions which timed out - std::unordered_set timeoutSessions; + std::unordered_set timeoutSessions; for (auto& p : timeSeenForSessions) { auto& signHash = p.first; int64_t firstSeenTime = p.second.first; @@ -1020,7 +1021,7 @@ void CSigSharesManager::Cleanup() { // Now delete sessions which are for inactive quorums LOCK(cs); - std::unordered_set inactiveQuorumSessions; + std::unordered_set inactiveQuorumSessions; sigShares.ForEach([&](const SigShareKey& k, const CSigShare& sigShare) { if (quorumsToCheck.count(std::make_pair((Consensus::LLMQType)sigShare.llmqType, sigShare.quorumHash))) { inactiveQuorumSessions.emplace(sigShare.GetSignHash()); diff --git a/src/llmq/quorums_signing_shares.h b/src/llmq/quorums_signing_shares.h index c843a9890..3f11c98b5 100644 --- a/src/llmq/quorums_signing_shares.h +++ b/src/llmq/quorums_signing_shares.h @@ -9,6 +9,7 @@ #include "chainparams.h" #include "net.h" #include "random.h" +#include "saltedhasher.h" #include "serialize.h" #include "sync.h" #include "tinyformat.h" @@ -28,29 +29,6 @@ namespace llmq { // typedef std::pair SigShareKey; -} - -namespace std { - template <> - struct hash - { - std::size_t operator()(const llmq::SigShareKey& k) const - { - return (std::size_t)((k.second + 1) * k.first.GetCheapHash()); - } - }; - template <> - struct hash> - { - std::size_t operator()(const std::pair& k) const - { - return (std::size_t)((k.first + 1) * k.second.GetCheapHash()); - } - }; -} - -namespace llmq -{ // this one does not get transmitted over the wire as it is batched inside CBatchedSigShares class CSigShare @@ -158,7 +136,7 @@ template class SigShareMap { private: - std::unordered_map> internalMap; + std::unordered_map, StaticSaltedHasher> internalMap; public: bool Add(const SigShareKey& k, const T& v) @@ -308,14 +286,14 @@ public: CSigSharesInv knows; }; // TODO limit number of sessions per node - std::unordered_map sessions; + std::unordered_map sessions; SigShareMap pendingIncomingSigShares; SigShareMap requestedSigShares; // elements are added whenever we receive a valid sig share from this node // this triggers us to send inventory items to him as he seems to be interested in these - std::unordered_set> interestedIn; + std::unordered_set, StaticSaltedHasher> interestedIn; bool banned{false}; @@ -347,7 +325,7 @@ private: SigShareMap sigShares; // stores time of first and last receivedSigShare. Used to detect timeouts - std::unordered_map> timeSeenForSessions; + std::unordered_map, StaticSaltedHasher> timeSeenForSessions; std::unordered_map nodeStates; SigShareMap> sigSharesRequested; @@ -386,10 +364,15 @@ private: bool VerifySigSharesInv(NodeId from, const CSigSharesInv& inv); bool PreVerifyBatchedSigShares(NodeId nodeId, const CBatchedSigShares& batchedSigShares, bool& retBan); - void CollectPendingSigSharesToVerify(size_t maxUniqueSessions, std::unordered_map>& retSigShares, std::unordered_map, CQuorumCPtr>& retQuorums); + void CollectPendingSigSharesToVerify(size_t maxUniqueSessions, + std::unordered_map>& retSigShares, + std::unordered_map, CQuorumCPtr, StaticSaltedHasher>& retQuorums); bool ProcessPendingSigShares(CConnman& connman); - void ProcessPendingSigSharesFromNode(NodeId nodeId, const std::vector& sigShares, const std::unordered_map, CQuorumCPtr>& quorums, CConnman& connman); + void ProcessPendingSigSharesFromNode(NodeId nodeId, + const std::vector& sigShares, + const std::unordered_map, CQuorumCPtr, StaticSaltedHasher>& quorums, + CConnman& connman); void ProcessSigShare(NodeId nodeId, const CSigShare& sigShare, CConnman& connman, const CQuorumCPtr& quorum); void TryRecoverSig(const CQuorumCPtr& quorum, const uint256& id, const uint256& msgHash, CConnman& connman); @@ -402,9 +385,9 @@ private: void BanNode(NodeId nodeId); bool SendMessages(); - void CollectSigSharesToRequest(std::unordered_map>& sigSharesToRequest); - void CollectSigSharesToSend(std::unordered_map>& sigSharesToSend); - void CollectSigSharesToAnnounce(std::unordered_map>& sigSharesToAnnounce); + void CollectSigSharesToRequest(std::unordered_map>& sigSharesToRequest); + void CollectSigSharesToSend(std::unordered_map>& sigSharesToSend); + void CollectSigSharesToAnnounce(std::unordered_map>& sigSharesToAnnounce); bool SignPendingSigShares(); void WorkThreadMain(); };