From 3019ad78f92b53e4ca5ca5277d8a33f0cfdb02a1 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 1 Dec 2022 19:34:11 +0300 Subject: [PATCH] fix(consensus)!: avoid using the same mn twice in one indexed quorum (#5086) --- src/llmq/utils.cpp | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/llmq/utils.cpp b/src/llmq/utils.cpp index ddf803380a..da4ec2fd0d 100644 --- a/src/llmq/utils.cpp +++ b/src/llmq/utils.cpp @@ -341,10 +341,21 @@ std::vector> BuildNewQuorumQuarterMembers(cons auto idx = 0; for (auto i = 0; i < nQuorums; ++i) { auto usedMNsCount = MnsUsedAtHIndexed[i].GetAllMNsCount(); + auto updated{false}; + auto initial_loop_idx = idx; while (quarterQuorumMembers[i].size() < quarterSize && (usedMNsCount + quarterQuorumMembers[i].size() < sortedCombinedMnsList.size())) { + bool skip{true}; if (!MnsUsedAtHIndexed[i].HasMN(sortedCombinedMnsList[idx]->proTxHash)) { - quarterQuorumMembers[i].push_back(sortedCombinedMnsList[idx]); - } else { + try { + // NOTE: AddMN is the one that can throw exceptions, must be exicuted first + MnsUsedAtHIndexed[i].AddMN(sortedCombinedMnsList[idx]); + quarterQuorumMembers[i].push_back(sortedCombinedMnsList[idx]); + updated = true; + skip = false; + } catch (const std::runtime_error& e) { + } + } + if (skip) { if (firstSkippedIndex == 0) { firstSkippedIndex = idx; skipList.push_back(idx); @@ -355,6 +366,15 @@ std::vector> BuildNewQuorumQuarterMembers(cons if (++idx == sortedCombinedMnsList.size()) { idx = 0; } + if (idx == initial_loop_idx) { + // we made full "while" loop + if (!updated) { + // there are not enough MNs, there is nothing we can do here + return std::vector>(nQuorums); + } + // reset and try again + updated = false; + } } }