Skip to content

Commit

Permalink
llmq|init|test: Add "mode" to -llmq-qvvec-sync parameter (#4030)
Browse files Browse the repository at this point in the history
* llmq|init|test: Add "mode" to -llmq-qvvec-sync parameter

This changes the paramter from `-llmq-qvvec-sync=<quorum_name>` to `-llmq-qvvec-sync=<quorum_name:mode>`

With the following definitions:

- `quorum_name`: Internal name of the quorum type
- `mode=0` - Sync always from all quorums of the type defined by `quorum_name`
- `mode=1` - Sync only if member of any from all other quorum of the type defined by `quorum_name`

`-llmq-qvvec-sync=llmq_100_67:0` To always request qvvec's from all `LLMQ_100_67`.
`-llmq-qvvec-sync=llmq_100_67:1` Only request if type member.

This means, if platform enables this on all MNs with `mode=0` we will
have all nodes asking new quorum for their verification vector instead
of only `24*100` at max.

* llmq: Adjust GetQuorumRecoveryStartOffset to use all MNs

* Turn `QvvecSyncMode` into `enum class`

Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
  • Loading branch information
xdustinface and UdjinM6 authored Mar 16, 2021
1 parent 95e8492 commit 4feb38b
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 77 deletions.
4 changes: 2 additions & 2 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ std::string HelpMessage(HelpMessageMode mode)

strUsage += HelpMessageGroup(_("Masternode options:"));
strUsage += HelpMessageOpt("-llmq-data-recovery=<n>", strprintf(_("Enable automated quorum data recovery (default: %u)"), llmq::DEFAULT_ENABLE_QUORUM_DATA_RECOVERY));
strUsage += HelpMessageOpt("-llmq-qvvec-sync=<quorum name>", _("Defines from which LLMQ type the masternode should sync quorum verification vectors. Can be used multiple times with different LLMQ types."));
strUsage += HelpMessageOpt("-llmq-qvvec-sync=<quorum_name:mode>", strprintf(_("Defines from which LLMQ type the masternode should sync quorum verification vectors. Can be used multiple times with different LLMQ types. (mode: %d (sync always from all quorums of the type defined by \"quorum_name\"), %d (sync from all quorums of the type defined by \"quorum_name\") if member of any of the quorums"), (int32_t)llmq::QvvecSyncMode::Always, (int32_t)llmq::QvvecSyncMode::OnlyIfTypeMember));
strUsage += HelpMessageOpt("-masternodeblsprivkey=<hex>", _("Set the masternode BLS private key and enable the client to act as a masternode"));
strUsage += HelpMessageOpt("-platform-user=<user>", _("Set the username for the \"platform user\", a restricted user intended to be used by Dash Platform, to the specified username."));

Expand Down Expand Up @@ -1618,7 +1618,7 @@ bool AppInitParameterInteraction()

try {
const bool fRecoveryEnabled{llmq::CLLMQUtils::QuorumDataRecoveryEnabled()};
const bool fQuorumVvecRequestsEnabled{llmq::CLLMQUtils::GetEnabledQuorumVvecSyncTypes().size() > 0};
const bool fQuorumVvecRequestsEnabled{llmq::CLLMQUtils::GetEnabledQuorumVvecSyncEntries().size() > 0};
if (!fRecoveryEnabled && fQuorumVvecRequestsEnabled) {
InitWarning("-llmq-qvvec-sync set but recovery is disabled due to -llmq-data-recovery=0");
}
Expand Down
33 changes: 14 additions & 19 deletions src/llmq/quorums.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ void CQuorumManager::TriggerQuorumDataRecoveryThreads(const CBlockIndex* pIndex)
return;
}

const std::set<Consensus::LLMQType> setQuorumVvecSyncTypes = CLLMQUtils::GetEnabledQuorumVvecSyncTypes();
const std::map<Consensus::LLMQType, QvvecSyncMode> mapQuorumVvecSync = CLLMQUtils::GetEnabledQuorumVvecSyncEntries();

LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- Process block %s\n", __func__, pIndex->GetBlockHash().ToString());

Expand All @@ -211,9 +211,11 @@ void CQuorumManager::TriggerQuorumDataRecoveryThreads(const CBlockIndex* pIndex)

uint16_t nDataMask{0};
const bool fWeAreQuorumMember = pQuorum->IsValidMember(activeMasternodeInfo.proTxHash);
const bool fTypeRequestsEnabled = setQuorumVvecSyncTypes.count(pQuorum->qc.llmqType) > 0;
const bool fSyncForTypeEnabled = mapQuorumVvecSync.count(pQuorum->qc.llmqType) > 0;
const QvvecSyncMode syncMode = fSyncForTypeEnabled ? mapQuorumVvecSync.at(pQuorum->qc.llmqType) : QvvecSyncMode::Invalid;
const bool fSyncCurrent = syncMode == QvvecSyncMode::Always || (syncMode == QvvecSyncMode::OnlyIfTypeMember && fWeAreQuorumTypeMember);

if ((fWeAreQuorumMember || (fWeAreQuorumTypeMember && fTypeRequestsEnabled)) && pQuorum->quorumVvec == nullptr) {
if ((fWeAreQuorumMember || (fSyncForTypeEnabled && fSyncCurrent)) && pQuorum->quorumVvec == nullptr) {
nDataMask |= llmq::CQuorumDataRequest::QUORUM_VERIFICATION_VECTOR;
}

Expand Down Expand Up @@ -512,23 +514,16 @@ CQuorumCPtr CQuorumManager::GetQuorum(Consensus::LLMQType llmqType, const CBlock

size_t CQuorumManager::GetQuorumRecoveryStartOffset(const CQuorumCPtr pQuorum, const CBlockIndex* pIndex) const
{
const size_t nActiveQuorums = pQuorum->params.signingActiveQuorumCount + 1;
const std::vector<CQuorumCPtr> vecQuorums = ScanQuorums(pQuorum->params.type, pIndex, nActiveQuorums);
assert(vecQuorums.size() > 0);
std::set<uint256> setAllTypeMembers;
for (auto& q : vecQuorums) {
auto& vecValid = q->qc.validMembers;
for (size_t i = 0; i < vecValid.size(); ++i) {
if (vecValid[i]) {
setAllTypeMembers.emplace(q->members[i]->proTxHash);
}
}
}
std::vector<uint256> vecAllTypeMembers{setAllTypeMembers.begin(), setAllTypeMembers.end()};
std::sort(vecAllTypeMembers.begin(), vecAllTypeMembers.end());
auto mns = deterministicMNManager->GetListForBlock(pIndex);
std::vector<uint256> vecProTxHashes;
vecProTxHashes.reserve(mns.GetValidMNsCount());
mns.ForEachMN(true, [&](const CDeterministicMNCPtr& pMasternode) {
vecProTxHashes.emplace_back(pMasternode->proTxHash);
});
std::sort(vecProTxHashes.begin(), vecProTxHashes.end());
size_t nIndex{0};
for (size_t i = 0; i < vecAllTypeMembers.size(); ++i) {
if (activeMasternodeInfo.proTxHash == vecAllTypeMembers[i]) {
for (size_t i = 0; i < vecProTxHashes.size(); ++i) {
if (activeMasternodeInfo.proTxHash == vecProTxHashes[i]) {
nIndex = i;
break;
}
Expand Down
43 changes: 35 additions & 8 deletions src/llmq/quorums_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,26 +324,53 @@ bool CLLMQUtils::QuorumDataRecoveryEnabled()
return gArgs.GetBoolArg("-llmq-data-recovery", DEFAULT_ENABLE_QUORUM_DATA_RECOVERY);
}

std::set<Consensus::LLMQType> CLLMQUtils::GetEnabledQuorumVvecSyncTypes()
std::map<Consensus::LLMQType, QvvecSyncMode> CLLMQUtils::GetEnabledQuorumVvecSyncEntries()
{
std::set<Consensus::LLMQType> setQuorumVvecSyncTypes;
for (const std::string& strLLMQType : gArgs.GetArgs("-llmq-qvvec-sync")) {
std::map<Consensus::LLMQType, QvvecSyncMode> mapQuorumVvecSyncEntries;
for (const auto& strEntry : gArgs.GetArgs("-llmq-qvvec-sync")) {
Consensus::LLMQType llmqType = Consensus::LLMQ_NONE;
QvvecSyncMode mode{QvvecSyncMode::Invalid};
std::istringstream ssEntry(strEntry);
std::string strLLMQType, strMode, strTest;
const bool fLLMQTypePresent = std::getline(ssEntry, strLLMQType, ':') && strLLMQType != "";
const bool fModePresent = std::getline(ssEntry, strMode, ':') && strMode != "";
const bool fTooManyEntries = static_cast<bool>(std::getline(ssEntry, strTest, ':'));
if (!fLLMQTypePresent || !fModePresent || fTooManyEntries) {
throw std::invalid_argument(strprintf("Invalid format in -llmq-qvvec-sync: %s", strEntry));
}
for (const auto& p : Params().GetConsensus().llmqs) {
if (p.second.name == strLLMQType) {
llmqType = p.first;
break;
}
}
if (llmqType == Consensus::LLMQ_NONE) {
throw std::invalid_argument(strprintf("Invalid llmqType in -llmq-qvvec-sync: %s", strLLMQType));
throw std::invalid_argument(strprintf("Invalid llmqType in -llmq-qvvec-sync: %s", strEntry));
}
if (mapQuorumVvecSyncEntries.count(llmqType) > 0) {
throw std::invalid_argument(strprintf("Duplicated llmqType in -llmq-qvvec-sync: %s", strEntry));
}

int32_t nMode;
if (ParseInt32(strMode, &nMode)) {
switch (nMode) {
case (int32_t)QvvecSyncMode::Always:
mode = QvvecSyncMode::Always;
break;
case (int32_t)QvvecSyncMode::OnlyIfTypeMember:
mode = QvvecSyncMode::OnlyIfTypeMember;
break;
default:
mode = QvvecSyncMode::Invalid;
break;
}
}
if (setQuorumVvecSyncTypes.count(llmqType) > 0) {
throw std::invalid_argument(strprintf("Duplicated llmqType in -llmq-qvvec-sync: %s", strLLMQType));
if (mode == QvvecSyncMode::Invalid) {
throw std::invalid_argument(strprintf("Invalid mode in -llmq-qvvec-sync: %s", strEntry));
}
setQuorumVvecSyncTypes.emplace(llmqType);
mapQuorumVvecSyncEntries.emplace(llmqType, mode);
}
return setQuorumVvecSyncTypes;
return mapQuorumVvecSyncEntries;
}

const Consensus::LLMQParams& GetLLMQParams(Consensus::LLMQType llmqType)
Expand Down
10 changes: 8 additions & 2 deletions src/llmq/quorums_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ extern VersionBitsCache llmq_versionbitscache;

static const bool DEFAULT_ENABLE_QUORUM_DATA_RECOVERY = true;

enum class QvvecSyncMode {
Invalid = -1,
Always = 0,
OnlyIfTypeMember = 1,
};

class CLLMQUtils
{
public:
Expand Down Expand Up @@ -57,8 +63,8 @@ class CLLMQUtils
/// Returns the state of `-llmq-data-recovery`
static bool QuorumDataRecoveryEnabled();

/// Returns the values given by `-llmq-qvvec-sync`
static std::set<Consensus::LLMQType> GetEnabledQuorumVvecSyncTypes();
/// Returns the parsed entries given by `-llmq-qvvec-sync`
static std::map<Consensus::LLMQType, QvvecSyncMode> GetEnabledQuorumVvecSyncEntries();

template<typename NodesContainer, typename Continue, typename Callback>
static void IterateNodesRandom(NodesContainer& nodeStates, Continue&& cont, Callback&& callback, FastRandomContext& rnd)
Expand Down
Loading

0 comments on commit 4feb38b

Please sign in to comment.