@@ -35,14 +35,46 @@ bool CRecoveredSigsDb::HasRecoveredSig(Consensus::LLMQType llmqType, const uint2
3535
3636bool CRecoveredSigsDb::HasRecoveredSigForId (Consensus::LLMQType llmqType, const uint256& id)
3737{
38+ int64_t t = GetTimeMillis ();
39+
40+ auto cacheKey = std::make_pair (llmqType, id);
41+ {
42+ LOCK (cs);
43+ auto it = hasSigForIdCache.find (cacheKey);
44+ if (it != hasSigForIdCache.end ()) {
45+ it->second .second = t;
46+ return it->second .first ;
47+ }
48+ }
49+
50+
3851 auto k = std::make_tuple (' r' , (uint8_t )llmqType, id);
39- return db.Exists (k);
52+ bool ret = db.Exists (k);
53+
54+ LOCK (cs);
55+ hasSigForIdCache.emplace (cacheKey, std::make_pair (ret, t));
56+ return ret;
4057}
4158
4259bool CRecoveredSigsDb::HasRecoveredSigForSession (const uint256& signHash)
4360{
61+ int64_t t = GetTimeMillis ();
62+
63+ {
64+ LOCK (cs);
65+ auto it = hasSigForSessionCache.find (signHash);
66+ if (it != hasSigForSessionCache.end ()) {
67+ it->second .second = t;
68+ return it->second .first ;
69+ }
70+ }
71+
4472 auto k = std::make_tuple (' s' , signHash);
45- return db.Exists (k);
73+ bool ret = db.Exists (k);
74+
75+ LOCK (cs);
76+ hasSigForSessionCache.emplace (signHash, std::make_pair (ret, t));
77+ return ret;
4678}
4779
4880bool CRecoveredSigsDb::HasRecoveredSigForHash (const uint256& hash)
@@ -100,7 +132,8 @@ void CRecoveredSigsDb::WriteRecoveredSig(const llmq::CRecoveredSig& recSig)
100132 batch.Write (k3, std::make_pair (recSig.llmqType , recSig.id ));
101133
102134 // store by signHash
103- auto k4 = std::make_tuple (' s' , llmq::utils::BuildSignHash (recSig));
135+ auto signHash = llmq::utils::BuildSignHash (recSig);
136+ auto k4 = std::make_tuple (' s' , signHash);
104137 batch.Write (k4, (uint8_t )1 );
105138
106139 // remove the votedForId entry as we won't need it anymore
@@ -112,6 +145,39 @@ void CRecoveredSigsDb::WriteRecoveredSig(const llmq::CRecoveredSig& recSig)
112145 batch.Write (k6, (uint8_t )1 );
113146
114147 db.WriteBatch (batch);
148+
149+ {
150+ int64_t t = GetTimeMillis ();
151+
152+ LOCK (cs);
153+ hasSigForIdCache[std::make_pair ((Consensus::LLMQType)recSig.llmqType , recSig.id )] = std::make_pair (true , t);
154+ hasSigForSessionCache[signHash] = std::make_pair (true , t);
155+ }
156+ }
157+
158+ template <typename K>
159+ static void TruncateCacheMap (std::unordered_map<K, std::pair<bool , int64_t >>& m, size_t maxSize, size_t truncateThreshold)
160+ {
161+ typedef typename std::unordered_map<K, std::pair<bool , int64_t >> Map;
162+ typedef typename Map::iterator Iterator;
163+
164+ if (m.size () <= truncateThreshold) {
165+ return ;
166+ }
167+
168+ std::vector<Iterator> vec;
169+ vec.reserve (m.size ());
170+ for (auto it = m.begin (); it != m.end (); ++it) {
171+ vec.emplace_back (it);
172+ }
173+ // sort by last access time (descending order)
174+ std::sort (vec.begin (), vec.end (), [](const Iterator& it1, const Iterator& it2) {
175+ return it1->second .second > it2->second .second ;
176+ });
177+
178+ for (size_t i = maxSize; i < vec.size (); i++) {
179+ m.erase (vec[i]);
180+ }
115181}
116182
117183void CRecoveredSigsDb::CleanupOldRecoveredSigs (int64_t maxAge)
@@ -148,22 +214,33 @@ void CRecoveredSigsDb::CleanupOldRecoveredSigs(int64_t maxAge)
148214 }
149215
150216 CDBBatch batch (CLIENT_VERSION | ADDRV2_FORMAT);
151- for (auto & e : toDelete) {
152- CRecoveredSig recSig;
153- if (!ReadRecoveredSig (e.first , e.second , recSig)) {
154- continue ;
217+ {
218+ LOCK (cs);
219+ for (auto & e : toDelete) {
220+ CRecoveredSig recSig;
221+ if (!ReadRecoveredSig (e.first , e.second , recSig)) {
222+ continue ;
223+ }
224+
225+ auto signHash = llmq::utils::BuildSignHash (recSig);
226+
227+ auto k1 = std::make_tuple (' r' , recSig.llmqType , recSig.id );
228+ auto k2 = std::make_tuple (' r' , recSig.llmqType , recSig.id , recSig.msgHash );
229+ auto k3 = std::make_tuple (' h' , recSig.GetHash ());
230+ auto k4 = std::make_tuple (' s' , signHash);
231+ auto k5 = std::make_tuple (' v' , recSig.llmqType , recSig.id );
232+ batch.Erase (k1);
233+ batch.Erase (k2);
234+ batch.Erase (k3);
235+ batch.Erase (k4);
236+ batch.Erase (k5);
237+
238+ hasSigForIdCache.erase (std::make_pair ((Consensus::LLMQType)recSig.llmqType , recSig.id ));
239+ hasSigForSessionCache.erase (signHash);
155240 }
156241
157- auto k1 = std::make_tuple (' r' , recSig.llmqType , recSig.id );
158- auto k2 = std::make_tuple (' r' , recSig.llmqType , recSig.id , recSig.msgHash );
159- auto k3 = std::make_tuple (' h' , recSig.GetHash ());
160- auto k4 = std::make_tuple (' s' , llmq::utils::BuildSignHash (recSig));
161- auto k5 = std::make_tuple (' v' , recSig.llmqType , recSig.id );
162- batch.Erase (k1);
163- batch.Erase (k2);
164- batch.Erase (k3);
165- batch.Erase (k4);
166- batch.Erase (k5);
242+ TruncateCacheMap (hasSigForIdCache, MAX_CACHE_SIZE, MAX_CACHE_TRUNCATE_THRESHOLD);
243+ TruncateCacheMap (hasSigForSessionCache, MAX_CACHE_SIZE, MAX_CACHE_TRUNCATE_THRESHOLD);
167244 }
168245
169246 for (auto & e : toDelete2) {
0 commit comments