Skip to content

Commit bdca48c

Browse files
knstthepastaclaw
authored andcommitted
refactor: use CountedBucketMap for counting total amount of pending sigs
1 parent 355da45 commit bdca48c

3 files changed

Lines changed: 43 additions & 65 deletions

File tree

src/llmq/signing_shares.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -206,14 +206,14 @@ bool CSigSharesNodeState::GetSessionInfoByRecvId(uint32_t sessionId, SessionInfo
206206
return true;
207207
}
208208

209-
size_t CSigSharesNodeState::RemoveSession(const uint256& signHash)
209+
void CSigSharesNodeState::RemoveSession(const uint256& signHash)
210210
{
211211
if (const auto it = sessions.find(signHash); it != sessions.end()) {
212212
sessionByRecvId.erase(it->second.recvSessionId);
213213
sessions.erase(it);
214214
}
215215
requestedSigShares.EraseAllForSignHash(signHash);
216-
return pendingIncomingSigShares.EraseAllForSignHash(signHash);
216+
pendingIncomingSigShares.EraseAllForSignHash(signHash);
217217
}
218218

219219
//////////////////////
@@ -493,16 +493,18 @@ bool CSigSharesManager::TryAddPendingIncomingSigShare(NodeId nodeId, CSigSharesN
493493
__func__, MAX_PENDING_SIG_SHARES_PER_NODE, nodeId);
494494
return false;
495495
}
496-
if (m_pending_sig_shares_total >= MAX_PENDING_SIG_SHARES_TOTAL) {
496+
size_t total{0};
497+
for (const auto& [_, ns] : nodeStates) {
498+
// the size of nodeStates is limited by DEFAULT_MAX_PEER_CONNECTIONS(125) so it should not be performance issue
499+
// The name of variable is intentionally mentioned in comment to make this code snippet relevant for possible changes in future
500+
total += ns.pendingIncomingSigShares.Size();
501+
}
502+
if (total >= MAX_PENDING_SIG_SHARES_TOTAL) {
497503
LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- global pending sig shares cap reached (%d), dropping sigShare. node=%d\n",
498504
__func__, MAX_PENDING_SIG_SHARES_TOTAL, nodeId);
499505
return false;
500506
}
501-
if (!nodeState.pendingIncomingSigShares.Add(sigShare.GetKey(), sigShare)) {
502-
return false;
503-
}
504-
++m_pending_sig_shares_total;
505-
return true;
507+
return nodeState.pendingIncomingSigShares.Add(sigShare.GetKey(), sigShare);
506508
}
507509

508510
bool CSigSharesManager::CollectPendingSigSharesToVerify(
@@ -544,7 +546,7 @@ bool CSigSharesManager::CollectPendingSigSharesToVerify(
544546
retSigShares[nodeId].emplace_back(sigShare);
545547
++sharesAdded;
546548
}
547-
m_pending_sig_shares_total -= ns.pendingIncomingSigShares.Erase(sigShare.GetKey());
549+
ns.pendingIncomingSigShares.Erase(sigShare.GetKey());
548550
return !ns.pendingIncomingSigShares.Empty();
549551
},
550552
rnd);
@@ -1399,7 +1401,6 @@ void CSigSharesManager::Cleanup()
13991401
AssertLockHeld(cs);
14001402
sigSharesRequested.Erase(k);
14011403
});
1402-
m_pending_sig_shares_total -= it->second.pendingIncomingSigShares.Size();
14031404
nodeStates.erase(nodeId);
14041405
}
14051406
}
@@ -1409,7 +1410,7 @@ void CSigSharesManager::RemoveSigSharesForSession(const uint256& signHash)
14091410
AssertLockHeld(cs);
14101411

14111412
for (auto& [_, nodeState] : nodeStates) {
1412-
m_pending_sig_shares_total -= nodeState.RemoveSession(signHash);
1413+
nodeState.RemoveSession(signHash);
14131414
}
14141415

14151416
sigSharesRequested.EraseAllForSignHash(signHash);
@@ -1431,7 +1432,6 @@ void CSigSharesManager::RemoveNodesIf(std::function<bool(NodeId)> predicate)
14311432
AssertLockHeld(cs);
14321433
sigSharesRequested.Erase(k);
14331434
});
1434-
m_pending_sig_shares_total -= it->second.pendingIncomingSigShares.Size();
14351435
it = nodeStates.erase(it);
14361436
} else {
14371437
++it;
@@ -1460,7 +1460,7 @@ void CSigSharesManager::MarkAsBanned(NodeId nodeId)
14601460
sigSharesRequested.Erase(k);
14611461
});
14621462
nodeState.requestedSigShares.Clear();
1463-
m_pending_sig_shares_total -= nodeState.pendingIncomingSigShares.Clear();
1463+
nodeState.pendingIncomingSigShares.Clear();
14641464
nodeState.banned = true;
14651465
}
14661466

src/llmq/signing_shares.h

Lines changed: 17 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -188,36 +188,31 @@ class CountedBucketMap
188188
return true;
189189
}
190190

191-
size_t Erase(const SigShareKey& k)
191+
void Erase(const SigShareKey& k)
192192
{
193193
auto it = m_data.find(k.first);
194194
if (it == m_data.end()) {
195-
return 0;
195+
return;
196196
}
197-
const size_t n = it->second.erase(k.second);
198-
m_num_entries -= n;
197+
m_num_entries -= it->second.erase(k.second);
199198
if (it->second.empty()) {
200199
m_data.erase(it);
201200
}
202-
return n;
203201
}
204202

205-
size_t EraseBucket(const uint256& signHash)
203+
void EraseBucket(const uint256& signHash)
206204
{
207205
auto it = m_data.find(signHash);
208206
if (it == m_data.end()) {
209-
return 0;
207+
return;
210208
}
211-
const size_t n = it->second.size();
212-
m_num_entries -= n;
209+
m_num_entries -= it->second.size();
213210
m_data.erase(it);
214-
return n;
215211
}
216212

217213
template<typename F>
218-
size_t EraseIf(F&& f)
214+
void EraseIf(F&& f)
219215
{
220-
size_t erased{0};
221216
for (auto it = m_data.begin(); it != m_data.end(); ) {
222217
SigShareKey k;
223218
k.first = it->first;
@@ -226,7 +221,6 @@ class CountedBucketMap
226221
if (f(k, jt->second)) {
227222
jt = it->second.erase(jt);
228223
--m_num_entries;
229-
++erased;
230224
} else {
231225
++jt;
232226
}
@@ -237,15 +231,12 @@ class CountedBucketMap
237231
++it;
238232
}
239233
}
240-
return erased;
241234
}
242235

243-
size_t Clear()
236+
void Clear()
244237
{
245-
const size_t prev = m_num_entries;
246238
m_data.clear();
247239
m_num_entries = 0;
248-
return prev;
249240
}
250241
};
251242

@@ -261,14 +252,14 @@ class SigShareMap
261252
return internalMap.Emplace(k, v);
262253
}
263254

264-
size_t Erase(const SigShareKey& k)
255+
void Erase(const SigShareKey& k)
265256
{
266-
return internalMap.Erase(k);
257+
internalMap.Erase(k);
267258
}
268259

269-
size_t Clear()
260+
void Clear()
270261
{
271-
return internalMap.Clear();
262+
internalMap.Clear();
272263
}
273264

274265
[[nodiscard]] bool Has(const SigShareKey& k) const
@@ -346,15 +337,15 @@ class SigShareMap
346337
return &it->second;
347338
}
348339

349-
size_t EraseAllForSignHash(const uint256& signHash)
340+
void EraseAllForSignHash(const uint256& signHash)
350341
{
351-
return internalMap.EraseBucket(signHash);
342+
internalMap.EraseBucket(signHash);
352343
}
353344

354345
template<typename F>
355-
size_t EraseIf(F&& f)
346+
void EraseIf(F&& f)
356347
{
357-
return internalMap.EraseIf(f);
348+
internalMap.EraseIf(f);
358349
}
359350

360351
template<typename F>
@@ -423,10 +414,7 @@ class CSigSharesNodeState
423414
Session* GetSessionByRecvId(uint32_t sessionId);
424415
bool GetSessionInfoByRecvId(uint32_t sessionId, SessionInfo& retInfo);
425416

426-
// Returns the number of pending incoming sig shares that were dropped
427-
// as part of tearing this session down; other per-session structures
428-
// are erased unconditionally.
429-
size_t RemoveSession(const uint256& signHash);
417+
void RemoveSession(const uint256& signHash);
430418
};
431419

432420
class CSignedSession
@@ -471,10 +459,6 @@ class CSigSharesManager : public llmq::CRecoveredSigsListener
471459
mutable Mutex cs;
472460

473461
SigShareMap<CSigShare> sigShares GUARDED_BY(cs);
474-
// Running total of shares held in nodeStates[*].pendingIncomingSigShares.
475-
// Maintained explicitly so the global cap check in TryAddPendingIncomingSigShare
476-
// doesn't need to walk every peer on every admission.
477-
size_t m_pending_sig_shares_total GUARDED_BY(cs){0};
478462
Uint256HashMap<CSignedSession> signedSessions GUARDED_BY(cs);
479463

480464
// stores time of last receivedSigShare. Used to detect timeouts

src/test/llmq_utils_tests.cpp

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -114,29 +114,26 @@ BOOST_AUTO_TEST_CASE(sig_share_map_size_tracks_mutations)
114114
BOOST_CHECK(sig_share_map.Add(sig_share2.GetKey(), sig_share2));
115115
BOOST_CHECK_EQUAL(sig_share_map.Size(), 2U);
116116

117-
BOOST_CHECK_EQUAL(sig_share_map.Erase(sig_share1.GetKey()), 1U);
118-
BOOST_CHECK_EQUAL(sig_share_map.Erase(sig_share1.GetKey()), 0U);
117+
sig_share_map.Erase(sig_share1.GetKey());
118+
sig_share_map.Erase(sig_share1.GetKey());
119119
BOOST_CHECK_EQUAL(sig_share_map.Size(), 1U);
120120

121-
BOOST_CHECK_EQUAL(sig_share_map.EraseAllForSignHash(sig_share2.GetSignHash()), 1U);
122-
BOOST_CHECK_EQUAL(sig_share_map.EraseAllForSignHash(sig_share2.GetSignHash()), 0U);
121+
sig_share_map.EraseAllForSignHash(sig_share2.GetSignHash());
122+
sig_share_map.EraseAllForSignHash(sig_share2.GetSignHash());
123123
BOOST_CHECK_EQUAL(sig_share_map.Size(), 0U);
124124
BOOST_CHECK(sig_share_map.Empty());
125125

126126
BOOST_CHECK(sig_share_map.Add(sig_share1.GetKey(), sig_share1));
127127
BOOST_CHECK(sig_share_map.Add(sig_share2.GetKey(), sig_share2));
128-
BOOST_CHECK_EQUAL(sig_share_map.EraseIf([&](const SigShareKey& k, const CSigShare&) { return k == sig_share1.GetKey(); }), 1U);
128+
sig_share_map.EraseIf([&](const SigShareKey& k, const CSigShare&) { return k == sig_share1.GetKey(); });
129129
BOOST_CHECK_EQUAL(sig_share_map.Size(), 1U);
130130

131-
BOOST_CHECK_EQUAL(sig_share_map.Clear(), 1U);
132-
BOOST_CHECK_EQUAL(sig_share_map.Clear(), 0U);
131+
sig_share_map.Clear();
133132
BOOST_CHECK_EQUAL(sig_share_map.Size(), 0U);
134133
}
135134

136-
BOOST_AUTO_TEST_CASE(sig_share_map_bucket_erase_returns_bucket_size)
135+
BOOST_AUTO_TEST_CASE(sig_share_map_bucket_erase_updates_size)
137136
{
138-
// EraseAllForSignHash must report the total number of entries evicted for the bucket,
139-
// so callers can maintain accurate running totals (e.g. the global pending sig-share cap).
140137
SigShareMap<CSigShare> sig_share_map;
141138
const auto sign_hash = MakeSigShare(1).GetSignHash();
142139

@@ -149,7 +146,7 @@ BOOST_AUTO_TEST_CASE(sig_share_map_bucket_erase_returns_bucket_size)
149146
}
150147
BOOST_CHECK_EQUAL(sig_share_map.Size(), 5U);
151148

152-
BOOST_CHECK_EQUAL(sig_share_map.EraseAllForSignHash(sign_hash), 5U);
149+
sig_share_map.EraseAllForSignHash(sign_hash);
153150
BOOST_CHECK(sig_share_map.Empty());
154151
}
155152

@@ -163,18 +160,15 @@ BOOST_AUTO_TEST_CASE(pending_sig_shares_session_removal_updates_count)
163160
BOOST_CHECK(node_state.pendingIncomingSigShares.Add(sig_share2.GetKey(), sig_share2));
164161
BOOST_CHECK_EQUAL(node_state.pendingIncomingSigShares.Size(), 2U);
165162

166-
// RemoveSession must report the number of pending shares actually dropped so the manager's
167-
// global pending-share counter can be decremented in lockstep.
168-
BOOST_CHECK_EQUAL(node_state.RemoveSession(sig_share1.GetSignHash()), 1U);
163+
node_state.RemoveSession(sig_share1.GetSignHash());
169164
BOOST_CHECK_EQUAL(node_state.pendingIncomingSigShares.Size(), 1U);
170165
BOOST_CHECK(!node_state.pendingIncomingSigShares.Has(sig_share1.GetKey()));
171166
BOOST_CHECK(node_state.pendingIncomingSigShares.Has(sig_share2.GetKey()));
172167

173-
// Removing the same session twice is idempotent and reports zero on the second call.
174-
BOOST_CHECK_EQUAL(node_state.RemoveSession(sig_share1.GetSignHash()), 0U);
175-
176-
// Removing a session that never had pending shares must also report zero.
177-
BOOST_CHECK_EQUAL(node_state.RemoveSession(MakeSigShare(3).GetSignHash()), 0U);
168+
// Removing the same session twice, or a session with no pending shares, is a no-op.
169+
node_state.RemoveSession(sig_share1.GetSignHash());
170+
node_state.RemoveSession(MakeSigShare(3).GetSignHash());
171+
BOOST_CHECK_EQUAL(node_state.pendingIncomingSigShares.Size(), 1U);
178172
}
179173

180174
BOOST_AUTO_TEST_CASE(deterministic_outbound_connection_test)

0 commit comments

Comments
 (0)