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(); };