refactor/feat: Refactor and add safety belts in llmq utils (#5378)

## Issue being fixed or feature implemented
We use `pQuorumBaseBlockIndex` name when we shouldn't and we don't check
that quorum types and block indexes provided as input params in llmq
utils satisfy our requirements. This is kind of ok-ish as long as we use
these functions appropriately but it's better to make things clearer and
to have actual checks imo.

noticed this while reviewing #5366 

## What was done?
Rename `pQuorumBaseBlockIndex` to `pCycleQuorumBaseBlockIndex`/`pindex`
in a few places. Check that quorum types and block indexes have expected
values.

## How Has This Been Tested?
run tests locally

## Breaking Changes
n/a

## Checklist:
- [x] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have added or updated relevant unit/integration/functional/e2e
tests
- [ ] I have made corresponding changes to the documentation
- [x] I have assigned this pull request to a milestone _(for repository
code-owners and collaborators only)_
This commit is contained in:
UdjinM6 2023-05-20 17:21:21 +03:00 committed by GitHub
parent e3a97b0156
commit 8bf40ea589
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 56 additions and 32 deletions

View File

@ -44,28 +44,29 @@ namespace utils
static std::vector<CDeterministicMNCPtr> ComputeQuorumMembers(Consensus::LLMQType llmqType, const CBlockIndex* pQuorumBaseBlockIndex); static std::vector<CDeterministicMNCPtr> ComputeQuorumMembers(Consensus::LLMQType llmqType, const CBlockIndex* pQuorumBaseBlockIndex);
static std::vector<std::vector<CDeterministicMNCPtr>> ComputeQuorumMembersByQuarterRotation(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pCycleQuorumBaseBlockIndex); static std::vector<std::vector<CDeterministicMNCPtr>> ComputeQuorumMembersByQuarterRotation(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pCycleQuorumBaseBlockIndex);
static std::vector<std::vector<CDeterministicMNCPtr>> BuildNewQuorumQuarterMembers(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pQuorumBaseBlockIndex, const PreviousQuorumQuarters& quarters); static std::vector<std::vector<CDeterministicMNCPtr>> BuildNewQuorumQuarterMembers(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pCycleQuorumBaseBlockIndex, const PreviousQuorumQuarters& quarters);
static PreviousQuorumQuarters GetPreviousQuorumQuarterMembers(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pBlockHMinusCIndex, const CBlockIndex* pBlockHMinus2CIndex, const CBlockIndex* pBlockHMinus3CIndex, int nHeight); static PreviousQuorumQuarters GetPreviousQuorumQuarterMembers(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pBlockHMinusCIndex, const CBlockIndex* pBlockHMinus2CIndex, const CBlockIndex* pBlockHMinus3CIndex, int nHeight);
static std::vector<std::vector<CDeterministicMNCPtr>> GetQuorumQuarterMembersBySnapshot(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pQuorumBaseBlockIndex, const llmq::CQuorumSnapshot& snapshot, int nHeights); static std::vector<std::vector<CDeterministicMNCPtr>> GetQuorumQuarterMembersBySnapshot(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pCycleQuorumBaseBlockIndex, const llmq::CQuorumSnapshot& snapshot, int nHeights);
static std::pair<CDeterministicMNList, CDeterministicMNList> GetMNUsageBySnapshot(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pQuorumBaseBlockIndex, const llmq::CQuorumSnapshot& snapshot, int nHeight); static std::pair<CDeterministicMNList, CDeterministicMNList> GetMNUsageBySnapshot(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pCycleQuorumBaseBlockIndex, const llmq::CQuorumSnapshot& snapshot, int nHeight);
static void BuildQuorumSnapshot(const Consensus::LLMQParams& llmqParams, const CDeterministicMNList& allMns, const CDeterministicMNList& mnUsedAtH, std::vector<CDeterministicMNCPtr>& sortedCombinedMns, CQuorumSnapshot& quorumSnapshot, int nHeight, std::vector<int>& skipList, const CBlockIndex* pQuorumBaseBlockIndex); static void BuildQuorumSnapshot(const Consensus::LLMQParams& llmqParams, const CDeterministicMNList& allMns, const CDeterministicMNList& mnUsedAtH, std::vector<CDeterministicMNCPtr>& sortedCombinedMns, CQuorumSnapshot& quorumSnapshot, int nHeight, std::vector<int>& skipList, const CBlockIndex* pCycleQuorumBaseBlockIndex);
static bool IsInstantSendLLMQTypeShared(); static bool IsInstantSendLLMQTypeShared();
void PreComputeQuorumMembers(const CBlockIndex* pQuorumBaseBlockIndex, bool reset_cache) void PreComputeQuorumMembers(const CBlockIndex* pindex, bool reset_cache)
{ {
for (const Consensus::LLMQParams& params : GetEnabledQuorumParams(pQuorumBaseBlockIndex->pprev)) { for (const Consensus::LLMQParams& params : GetEnabledQuorumParams(pindex->pprev)) {
if (IsQuorumRotationEnabled(params, pQuorumBaseBlockIndex) && (pQuorumBaseBlockIndex->nHeight % params.dkgInterval == 0)) { if (IsQuorumRotationEnabled(params, pindex) && (pindex->nHeight % params.dkgInterval == 0)) {
GetAllQuorumMembers(params.type, pQuorumBaseBlockIndex, reset_cache); GetAllQuorumMembers(params.type, pindex, reset_cache);
} }
} }
} }
uint256 GetHashModifier(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pQuorumBaseBlockIndex) uint256 GetHashModifier(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pCycleQuorumBaseBlockIndex)
{ {
const CBlockIndex* pWorkBlockIndex = pQuorumBaseBlockIndex->GetAncestor(pQuorumBaseBlockIndex->nHeight - 8); ASSERT_IF_DEBUG(pCycleQuorumBaseBlockIndex->nHeight % llmqParams.dkgInterval == 0);
const CBlockIndex* pWorkBlockIndex = pCycleQuorumBaseBlockIndex->GetAncestor(pCycleQuorumBaseBlockIndex->nHeight - 8);
if (IsV20Active(pWorkBlockIndex)) { if (IsV20Active(pWorkBlockIndex)) {
// v20 is active: calculate modifier using the new way. // v20 is active: calculate modifier using the new way.
@ -83,7 +84,7 @@ uint256 GetHashModifier(const Consensus::LLMQParams& llmqParams, const CBlockInd
if (llmqParams.useRotation) { if (llmqParams.useRotation) {
return ::SerializeHash(std::make_pair(llmqParams.type, pWorkBlockIndex->GetBlockHash())); return ::SerializeHash(std::make_pair(llmqParams.type, pWorkBlockIndex->GetBlockHash()));
} }
return ::SerializeHash(std::make_pair(llmqParams.type, pQuorumBaseBlockIndex->GetBlockHash())); return ::SerializeHash(std::make_pair(llmqParams.type, pCycleQuorumBaseBlockIndex->GetBlockHash()));
} }
std::vector<CDeterministicMNCPtr> GetAllQuorumMembers(Consensus::LLMQType llmqType, const CBlockIndex* pQuorumBaseBlockIndex, bool reset_cache) std::vector<CDeterministicMNCPtr> GetAllQuorumMembers(Consensus::LLMQType llmqType, const CBlockIndex* pQuorumBaseBlockIndex, bool reset_cache)
@ -166,7 +167,7 @@ std::vector<CDeterministicMNCPtr> ComputeQuorumMembers(Consensus::LLMQType llmqT
bool HPMNOnly = (Params().GetConsensus().llmqTypePlatform == llmqType) && IsV19Active(pQuorumBaseBlockIndex); bool HPMNOnly = (Params().GetConsensus().llmqTypePlatform == llmqType) && IsV19Active(pQuorumBaseBlockIndex);
const auto& llmq_params_opt = GetLLMQParams(llmqType); const auto& llmq_params_opt = GetLLMQParams(llmqType);
assert(llmq_params_opt.has_value()); assert(llmq_params_opt.has_value());
if (llmq_params_opt->useRotation) { if (llmq_params_opt->useRotation || pQuorumBaseBlockIndex->nHeight % llmq_params_opt->dkgInterval != 0) {
ASSERT_IF_DEBUG(false); ASSERT_IF_DEBUG(false);
return {}; return {};
} }
@ -184,7 +185,10 @@ std::vector<std::vector<CDeterministicMNCPtr>> ComputeQuorumMembersByQuarterRota
const Consensus::LLMQType llmqType = llmqParams.type; const Consensus::LLMQType llmqType = llmqParams.type;
const int cycleLength = llmqParams.dkgInterval; const int cycleLength = llmqParams.dkgInterval;
assert(pCycleQuorumBaseBlockIndex->nHeight % cycleLength == 0); if (!llmqParams.useRotation || pCycleQuorumBaseBlockIndex->nHeight % llmqParams.dkgInterval != 0) {
ASSERT_IF_DEBUG(false);
return {};
}
const CBlockIndex* pBlockHMinusCIndex = pCycleQuorumBaseBlockIndex->GetAncestor(pCycleQuorumBaseBlockIndex->nHeight - cycleLength); const CBlockIndex* pBlockHMinusCIndex = pCycleQuorumBaseBlockIndex->GetAncestor(pCycleQuorumBaseBlockIndex->nHeight - cycleLength);
const CBlockIndex* pBlockHMinus2CIndex = pCycleQuorumBaseBlockIndex->GetAncestor(pCycleQuorumBaseBlockIndex->nHeight - 2 * cycleLength); const CBlockIndex* pBlockHMinus2CIndex = pCycleQuorumBaseBlockIndex->GetAncestor(pCycleQuorumBaseBlockIndex->nHeight - 2 * cycleLength);
@ -291,16 +295,21 @@ PreviousQuorumQuarters GetPreviousQuorumQuarterMembers(const Consensus::LLMQPara
} }
std::vector<std::vector<CDeterministicMNCPtr>> BuildNewQuorumQuarterMembers(const Consensus::LLMQParams& llmqParams, std::vector<std::vector<CDeterministicMNCPtr>> BuildNewQuorumQuarterMembers(const Consensus::LLMQParams& llmqParams,
const CBlockIndex* pQuorumBaseBlockIndex, const CBlockIndex* pCycleQuorumBaseBlockIndex,
const PreviousQuorumQuarters& previousQuarters) const PreviousQuorumQuarters& previousQuarters)
{ {
if (!llmqParams.useRotation || pCycleQuorumBaseBlockIndex->nHeight % llmqParams.dkgInterval != 0) {
ASSERT_IF_DEBUG(false);
return {};
}
size_t nQuorums = static_cast<size_t>(llmqParams.signingActiveQuorumCount); size_t nQuorums = static_cast<size_t>(llmqParams.signingActiveQuorumCount);
std::vector<std::vector<CDeterministicMNCPtr>> quarterQuorumMembers{nQuorums}; std::vector<std::vector<CDeterministicMNCPtr>> quarterQuorumMembers{nQuorums};
size_t quorumSize = static_cast<size_t>(llmqParams.size); size_t quorumSize = static_cast<size_t>(llmqParams.size);
auto quarterSize{quorumSize / 4}; auto quarterSize{quorumSize / 4};
const CBlockIndex* pWorkBlockIndex = pQuorumBaseBlockIndex->GetAncestor(pQuorumBaseBlockIndex->nHeight - 8); const CBlockIndex* pWorkBlockIndex = pCycleQuorumBaseBlockIndex->GetAncestor(pCycleQuorumBaseBlockIndex->nHeight - 8);
const auto modifier = GetHashModifier(llmqParams, pQuorumBaseBlockIndex); const auto modifier = GetHashModifier(llmqParams, pCycleQuorumBaseBlockIndex);
auto allMns = deterministicMNManager->GetListForBlock(pWorkBlockIndex); auto allMns = deterministicMNManager->GetListForBlock(pWorkBlockIndex);
@ -312,7 +321,7 @@ std::vector<std::vector<CDeterministicMNCPtr>> BuildNewQuorumQuarterMembers(cons
auto MnsNotUsedAtH = CDeterministicMNList(); auto MnsNotUsedAtH = CDeterministicMNList();
std::vector<CDeterministicMNList> MnsUsedAtHIndexed{nQuorums}; std::vector<CDeterministicMNList> MnsUsedAtHIndexed{nQuorums};
bool skipRemovedMNs = IsV19Active(pQuorumBaseBlockIndex) || (Params().NetworkIDString() == CBaseChainParams::TESTNET); bool skipRemovedMNs = IsV19Active(pCycleQuorumBaseBlockIndex) || (Params().NetworkIDString() == CBaseChainParams::TESTNET);
for (const size_t i : irange::range(nQuorums)) { for (const size_t i : irange::range(nQuorums)) {
for (const auto& mn : previousQuarters.quarterHMinusC[i]) { for (const auto& mn : previousQuarters.quarterHMinusC[i]) {
@ -391,7 +400,7 @@ std::vector<std::vector<CDeterministicMNCPtr>> BuildNewQuorumQuarterMembers(cons
} }
ss << "]"; ss << "]";
LogPrint(BCLog::LLMQ, "BuildNewQuorumQuarterMembers h[%d] sortedCombinedMns[%s]\n", LogPrint(BCLog::LLMQ, "BuildNewQuorumQuarterMembers h[%d] sortedCombinedMns[%s]\n",
pQuorumBaseBlockIndex->nHeight, ss.str()); pCycleQuorumBaseBlockIndex->nHeight, ss.str());
} }
std::vector<int> skipList; std::vector<int> skipList;
@ -438,22 +447,27 @@ std::vector<std::vector<CDeterministicMNCPtr>> BuildNewQuorumQuarterMembers(cons
CQuorumSnapshot quorumSnapshot = {}; CQuorumSnapshot quorumSnapshot = {};
BuildQuorumSnapshot(llmqParams, allMns, MnsUsedAtH, sortedCombinedMnsList, quorumSnapshot, pQuorumBaseBlockIndex->nHeight, skipList, pQuorumBaseBlockIndex); BuildQuorumSnapshot(llmqParams, allMns, MnsUsedAtH, sortedCombinedMnsList, quorumSnapshot, pCycleQuorumBaseBlockIndex->nHeight, skipList, pCycleQuorumBaseBlockIndex);
quorumSnapshotManager->StoreSnapshotForBlock(llmqParams.type, pQuorumBaseBlockIndex, quorumSnapshot); quorumSnapshotManager->StoreSnapshotForBlock(llmqParams.type, pCycleQuorumBaseBlockIndex, quorumSnapshot);
return quarterQuorumMembers; return quarterQuorumMembers;
} }
void BuildQuorumSnapshot(const Consensus::LLMQParams& llmqParams, const CDeterministicMNList& allMns, void BuildQuorumSnapshot(const Consensus::LLMQParams& llmqParams, const CDeterministicMNList& allMns,
const CDeterministicMNList& mnUsedAtH, std::vector<CDeterministicMNCPtr>& sortedCombinedMns, const CDeterministicMNList& mnUsedAtH, std::vector<CDeterministicMNCPtr>& sortedCombinedMns,
CQuorumSnapshot& quorumSnapshot, int nHeight, std::vector<int>& skipList, const CBlockIndex* pQuorumBaseBlockIndex) CQuorumSnapshot& quorumSnapshot, int nHeight, std::vector<int>& skipList, const CBlockIndex* pCycleQuorumBaseBlockIndex)
{ {
if (!llmqParams.useRotation || pCycleQuorumBaseBlockIndex->nHeight % llmqParams.dkgInterval != 0) {
ASSERT_IF_DEBUG(false);
return;
}
quorumSnapshot.activeQuorumMembers.resize(allMns.GetAllMNsCount()); quorumSnapshot.activeQuorumMembers.resize(allMns.GetAllMNsCount());
const auto modifier = GetHashModifier(llmqParams, pQuorumBaseBlockIndex); const auto modifier = GetHashModifier(llmqParams, pCycleQuorumBaseBlockIndex);
auto sortedAllMns = allMns.CalculateQuorum(allMns.GetAllMNsCount(), modifier); auto sortedAllMns = allMns.CalculateQuorum(allMns.GetAllMNsCount(), modifier);
LogPrint(BCLog::LLMQ, "BuildQuorumSnapshot h[%d] numMns[%d]\n", pQuorumBaseBlockIndex->nHeight, allMns.GetAllMNsCount()); LogPrint(BCLog::LLMQ, "BuildQuorumSnapshot h[%d] numMns[%d]\n", pCycleQuorumBaseBlockIndex->nHeight, allMns.GetAllMNsCount());
std::fill(quorumSnapshot.activeQuorumMembers.begin(), std::fill(quorumSnapshot.activeQuorumMembers.begin(),
quorumSnapshot.activeQuorumMembers.end(), quorumSnapshot.activeQuorumMembers.end(),
@ -476,14 +490,19 @@ void BuildQuorumSnapshot(const Consensus::LLMQParams& llmqParams, const CDetermi
} }
std::vector<std::vector<CDeterministicMNCPtr>> GetQuorumQuarterMembersBySnapshot(const Consensus::LLMQParams& llmqParams, std::vector<std::vector<CDeterministicMNCPtr>> GetQuorumQuarterMembersBySnapshot(const Consensus::LLMQParams& llmqParams,
const CBlockIndex* pQuorumBaseBlockIndex, const CBlockIndex* pCycleQuorumBaseBlockIndex,
const llmq::CQuorumSnapshot& snapshot, const llmq::CQuorumSnapshot& snapshot,
int nHeight) int nHeight)
{ {
if (!llmqParams.useRotation || pCycleQuorumBaseBlockIndex->nHeight % llmqParams.dkgInterval != 0) {
ASSERT_IF_DEBUG(false);
return {};
}
std::vector<CDeterministicMNCPtr> sortedCombinedMns; std::vector<CDeterministicMNCPtr> sortedCombinedMns;
{ {
const auto modifier = GetHashModifier(llmqParams, pQuorumBaseBlockIndex); const auto modifier = GetHashModifier(llmqParams, pCycleQuorumBaseBlockIndex);
const auto [MnsUsedAtH, MnsNotUsedAtH] = GetMNUsageBySnapshot(llmqParams, pQuorumBaseBlockIndex, snapshot, nHeight); const auto [MnsUsedAtH, MnsNotUsedAtH] = GetMNUsageBySnapshot(llmqParams, pCycleQuorumBaseBlockIndex, snapshot, nHeight);
// the list begins with all the unused MNs // the list begins with all the unused MNs
auto sortedMnsNotUsedAtH = MnsNotUsedAtH.CalculateQuorum(MnsNotUsedAtH.GetAllMNsCount(), modifier); auto sortedMnsNotUsedAtH = MnsNotUsedAtH.CalculateQuorum(MnsNotUsedAtH.GetAllMNsCount(), modifier);
sortedCombinedMns = std::move(sortedMnsNotUsedAtH); sortedCombinedMns = std::move(sortedMnsNotUsedAtH);
@ -500,7 +519,7 @@ std::vector<std::vector<CDeterministicMNCPtr>> GetQuorumQuarterMembersBySnapshot
} }
ss << "]"; ss << "]";
LogPrint(BCLog::LLMQ, "GetQuorumQuarterMembersBySnapshot h[%d] from[%d] sortedCombinedMns[%s]\n", LogPrint(BCLog::LLMQ, "GetQuorumQuarterMembersBySnapshot h[%d] from[%d] sortedCombinedMns[%s]\n",
pQuorumBaseBlockIndex->nHeight, nHeight, ss.str()); pCycleQuorumBaseBlockIndex->nHeight, nHeight, ss.str());
} }
size_t numQuorums = static_cast<size_t>(llmqParams.signingActiveQuorumCount); size_t numQuorums = static_cast<size_t>(llmqParams.signingActiveQuorumCount);
@ -566,15 +585,20 @@ std::vector<std::vector<CDeterministicMNCPtr>> GetQuorumQuarterMembersBySnapshot
} }
std::pair<CDeterministicMNList, CDeterministicMNList> GetMNUsageBySnapshot(const Consensus::LLMQParams& llmqParams, std::pair<CDeterministicMNList, CDeterministicMNList> GetMNUsageBySnapshot(const Consensus::LLMQParams& llmqParams,
const CBlockIndex* pQuorumBaseBlockIndex, const CBlockIndex* pCycleQuorumBaseBlockIndex,
const llmq::CQuorumSnapshot& snapshot, const llmq::CQuorumSnapshot& snapshot,
int nHeight) int nHeight)
{ {
if (!llmqParams.useRotation || pCycleQuorumBaseBlockIndex->nHeight % llmqParams.dkgInterval != 0) {
ASSERT_IF_DEBUG(false);
return {};
}
CDeterministicMNList usedMNs; CDeterministicMNList usedMNs;
CDeterministicMNList nonUsedMNs; CDeterministicMNList nonUsedMNs;
const CBlockIndex* pWorkBlockIndex = pQuorumBaseBlockIndex->GetAncestor(pQuorumBaseBlockIndex->nHeight - 8); const CBlockIndex* pWorkBlockIndex = pCycleQuorumBaseBlockIndex->GetAncestor(pCycleQuorumBaseBlockIndex->nHeight - 8);
const auto modifier = GetHashModifier(llmqParams, pQuorumBaseBlockIndex); const auto modifier = GetHashModifier(llmqParams, pCycleQuorumBaseBlockIndex);
auto allMns = deterministicMNManager->GetListForBlock(pWorkBlockIndex); auto allMns = deterministicMNManager->GetListForBlock(pWorkBlockIndex);
auto sortedAllMns = allMns.CalculateQuorum(allMns.GetAllMNsCount(), modifier); auto sortedAllMns = allMns.CalculateQuorum(allMns.GetAllMNsCount(), modifier);

View File

@ -57,8 +57,8 @@ namespace utils
// includes members which failed DKG // includes members which failed DKG
std::vector<CDeterministicMNCPtr> GetAllQuorumMembers(Consensus::LLMQType llmqType, const CBlockIndex* pQuorumBaseBlockIndex, bool reset_cache = false); std::vector<CDeterministicMNCPtr> GetAllQuorumMembers(Consensus::LLMQType llmqType, const CBlockIndex* pQuorumBaseBlockIndex, bool reset_cache = false);
void PreComputeQuorumMembers(const CBlockIndex* pQuorumBaseBlockIndex, bool reset_cache = false); void PreComputeQuorumMembers(const CBlockIndex* pindex, bool reset_cache = false);
uint256 GetHashModifier(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pQuorumBaseBlockIndex); uint256 GetHashModifier(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pCycleQuorumBaseBlockIndex);
uint256 BuildCommitmentHash(Consensus::LLMQType llmqType, const uint256& blockHash, const std::vector<bool>& validMembers, const CBLSPublicKey& pubKey, const uint256& vvecHash); uint256 BuildCommitmentHash(Consensus::LLMQType llmqType, const uint256& blockHash, const std::vector<bool>& validMembers, const CBLSPublicKey& pubKey, const uint256& vvecHash);
uint256 BuildSignHash(Consensus::LLMQType llmqType, const uint256& quorumHash, const uint256& id, const uint256& msgHash); uint256 BuildSignHash(Consensus::LLMQType llmqType, const uint256& quorumHash, const uint256& id, const uint256& msgHash);