Edge case fix for Rotation (#4803)

* Edge case fix

* Simpler syntax

* add a bit of documentation, and adjust scopes

* use a switch statment

* adjust how returning happens

Co-authored-by: pasta <pasta@dashboost.org>
This commit is contained in:
Odysseas Gabrielides 2022-04-25 22:11:44 +03:00 committed by GitHub
parent 476c25f3c7
commit a2e1f46cf4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -351,70 +351,78 @@ void CLLMQUtils::BuildQuorumSnapshot(const Consensus::LLMQParams& llmqParams, co
std::vector<std::vector<CDeterministicMNCPtr>> CLLMQUtils::GetQuorumQuarterMembersBySnapshot(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pQuorumBaseBlockIndex, const llmq::CQuorumSnapshot& snapshot, int nHeight) std::vector<std::vector<CDeterministicMNCPtr>> CLLMQUtils::GetQuorumQuarterMembersBySnapshot(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pQuorumBaseBlockIndex, const llmq::CQuorumSnapshot& snapshot, int nHeight)
{ {
auto numQuorums = static_cast<size_t>(llmqParams.signingActiveQuorumCount); std::vector<CDeterministicMNCPtr> sortedCombinedMns;
auto quorumSize = static_cast<size_t>(llmqParams.size); {
const CBlockIndex* pWorkBlockIndex = pQuorumBaseBlockIndex->GetAncestor(pQuorumBaseBlockIndex->nHeight - 8);
const auto modifier = ::SerializeHash(std::make_pair(llmqParams.type, pWorkBlockIndex->GetBlockHash()));
const auto [MnsUsedAtH, MnsNotUsedAtH] = CLLMQUtils::GetMNUsageBySnapshot(llmqParams.type, pQuorumBaseBlockIndex, snapshot, nHeight);
// the list begins with all the unused MNs
auto sortedMnsNotUsedAtH = MnsNotUsedAtH.CalculateQuorum(MnsNotUsedAtH.GetAllMNsCount(), modifier);
sortedCombinedMns = std::move(sortedMnsNotUsedAtH);
// Now add the already used MNs to the end of the list
auto sortedMnsUsedAtH = MnsUsedAtH.CalculateQuorum(MnsUsedAtH.GetAllMNsCount(), modifier);
std::move(sortedMnsUsedAtH.begin(), sortedMnsUsedAtH.end(), std::back_inserter(sortedCombinedMns));
}
if (sortedCombinedMns.empty()) return {};
auto numQuorums = size_t(llmqParams.signingActiveQuorumCount);
auto quorumSize = size_t(llmqParams.size);
auto quarterSize = quorumSize / 4; auto quarterSize = quorumSize / 4;
std::vector<std::vector<CDeterministicMNCPtr>> quarterQuorumMembers(numQuorums); std::vector<std::vector<CDeterministicMNCPtr>> quarterQuorumMembers(numQuorums);
const CBlockIndex* pWorkBlockIndex = pQuorumBaseBlockIndex->GetAncestor(pQuorumBaseBlockIndex->nHeight - 8); switch (snapshot.mnSkipListMode) {
auto modifier = ::SerializeHash(std::make_pair(llmqParams.type, pWorkBlockIndex->GetBlockHash())); case SnapshotSkipMode::MODE_NO_SKIPPING:
{
auto [MnsUsedAtH, MnsNotUsedAtH] = CLLMQUtils::GetMNUsageBySnapshot(llmqParams.type, pQuorumBaseBlockIndex, snapshot, nHeight);
auto sortedMnsUsedAtH = MnsUsedAtH.CalculateQuorum(MnsUsedAtH.GetAllMNsCount(), modifier);
auto sortedMnsNotUsedAtH = MnsNotUsedAtH.CalculateQuorum(MnsNotUsedAtH.GetAllMNsCount(), modifier);
auto sortedCombinedMns = std::move(sortedMnsNotUsedAtH);
for (auto& m : sortedMnsUsedAtH) {
sortedCombinedMns.push_back(std::move(m));
}
//Mode 0: No skipping
if (snapshot.mnSkipListMode == SnapshotSkipMode::MODE_NO_SKIPPING) {
auto itm = sortedCombinedMns.begin(); auto itm = sortedCombinedMns.begin();
for (auto i = 0; i < llmqParams.signingActiveQuorumCount; ++i) { for (auto i = 0; i < llmqParams.signingActiveQuorumCount; ++i) {
while (quarterQuorumMembers[i].size() < quarterSize) { while (quarterQuorumMembers[i].size() < quarterSize) {
quarterQuorumMembers[i].push_back(*itm); quarterQuorumMembers[i].push_back(*itm);
itm++; itm++;
if (itm == sortedCombinedMns.end()) if (itm == sortedCombinedMns.end()) {
itm = sortedCombinedMns.begin(); itm = sortedCombinedMns.begin();
} }
} }
} }
//Mode 1: List holds entries to be skipped return quarterQuorumMembers;
else if (snapshot.mnSkipListMode == SnapshotSkipMode::MODE_SKIPPING_ENTRIES) { }
size_t first_entry_index = {}; case SnapshotSkipMode::MODE_SKIPPING_ENTRIES: // List holds entries to be skipped
{
size_t first_entry_index{0};
std::vector<int> processesdSkipList; std::vector<int> processesdSkipList;
for (const auto& s : snapshot.mnSkipList) { for (const auto& s : snapshot.mnSkipList) {
if (first_entry_index == 0) { if (first_entry_index == 0) {
first_entry_index = s; first_entry_index = s;
processesdSkipList.push_back(s); processesdSkipList.push_back(s);
} else } else {
processesdSkipList.push_back(first_entry_index + s); processesdSkipList.push_back(first_entry_index + s);
} }
}
auto idx = 0; auto idx = 0;
auto itsk = processesdSkipList.begin(); auto itsk = processesdSkipList.begin();
for (auto i = 0; i < llmqParams.signingActiveQuorumCount; ++i) { for (auto i = 0; i < llmqParams.signingActiveQuorumCount; ++i) {
while (quarterQuorumMembers[i].size() < quarterSize) { while (quarterQuorumMembers[i].size() < quarterSize) {
if (itsk != processesdSkipList.end() && idx == *itsk) if (itsk != processesdSkipList.end() && idx == *itsk) {
itsk++; itsk++;
else } else {
quarterQuorumMembers[i].push_back(sortedCombinedMns[idx]); quarterQuorumMembers[i].push_back(sortedCombinedMns[idx]);
}
idx++; idx++;
if (idx == sortedCombinedMns.size()) if (idx == sortedCombinedMns.size()) {
idx = 0; idx = 0;
} }
} }
} }
//Mode 2: List holds entries to be kept
else if (snapshot.mnSkipListMode == SnapshotSkipMode::MODE_NO_SKIPPING_ENTRIES) {
//TODO Mode 2 will be written. Not used now
}
//Mode 3: Every node was skipped. Returning empty quarterQuorumMembers
return quarterQuorumMembers; return quarterQuorumMembers;
} }
case SnapshotSkipMode::MODE_NO_SKIPPING_ENTRIES: // List holds entries to be kept
case SnapshotSkipMode::MODE_ALL_SKIPPED: // Every node was skipped. Returning empty quarterQuorumMembers
default:
return {};
}
}
std::pair<CDeterministicMNList, CDeterministicMNList> CLLMQUtils::GetMNUsageBySnapshot(Consensus::LLMQType llmqType, const CBlockIndex* pQuorumBaseBlockIndex, const llmq::CQuorumSnapshot& snapshot, int nHeight) std::pair<CDeterministicMNList, CDeterministicMNList> CLLMQUtils::GetMNUsageBySnapshot(Consensus::LLMQType llmqType, const CBlockIndex* pQuorumBaseBlockIndex, const llmq::CQuorumSnapshot& snapshot, int nHeight)
{ {