Line data Source code
1 : // Copyright (c) 2018-2025 The Dash Core developers 2 : // Distributed under the MIT software license, see the accompanying 3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 : 5 : #include <llmq/options.h> 6 : 7 : #include <spork.h> 8 : #include <util/helpers.h> 9 : #include <util/std23.h> 10 : 11 : #include <chainparams.h> 12 : #include <consensus/params.h> 13 : #include <deploymentstatus.h> 14 : #include <util/system.h> 15 : #include <validation.h> 16 : 17 : #include <algorithm> 18 : #include <ranges> 19 : #include <string> 20 : #include <stdexcept> 21 : #include <thread> 22 : 23 : namespace llmq { 24 3308 : int16_t DEFAULT_WORKER_COUNT{std::clamp<int16_t>(std::thread::hardware_concurrency() / 2, 1, 4)}; 25 : 26 2161265 : static bool EvalSpork(const Consensus::LLMQType llmqType, const int64_t spork_value) 27 : { 28 2161265 : if (spork_value == 0) { 29 264875 : return true; 30 : } 31 1896390 : if (spork_value == 1 && llmqType != Consensus::LLMQType::LLMQ_100_67 && llmqType != Consensus::LLMQType::LLMQ_400_60 && llmqType != Consensus::LLMQType::LLMQ_400_85) { 32 0 : return true; 33 : } 34 1896390 : return false; 35 2161265 : } 36 : 37 2155784 : bool IsAllMembersConnectedEnabled(const Consensus::LLMQType llmqType, const CSporkManager& sporkman) 38 : { 39 2155784 : return EvalSpork(llmqType, sporkman.GetSporkValue(SPORK_21_QUORUM_ALL_CONNECTED)); 40 : } 41 : 42 222612 : bool IsQuorumDKGEnabled(const CSporkManager& sporkman) { return sporkman.IsSporkActive(SPORK_17_QUORUM_DKG_ENABLED); } 43 : 44 5466 : bool IsQuorumPoseEnabled(const Consensus::LLMQType llmqType, const CSporkManager& sporkman) 45 : { 46 5466 : return EvalSpork(llmqType, sporkman.GetSporkValue(SPORK_23_QUORUM_POSE)); 47 : } 48 : 49 : 50 3436092 : bool IsQuorumRotationEnabled(const Consensus::LLMQParams& llmqParams, gsl::not_null<const CBlockIndex*> pindex) 51 : { 52 3436092 : if (!llmqParams.useRotation) { 53 2504905 : return false; 54 : } 55 : 56 931187 : int cycleQuorumBaseHeight = pindex->nHeight - (pindex->nHeight % llmqParams.dkgInterval); 57 931187 : if (cycleQuorumBaseHeight < 1) { 58 22143 : return false; 59 : } 60 : // It should activate at least 1 block prior to the cycle start 61 909044 : return DeploymentActiveAfter(pindex->GetAncestor(cycleQuorumBaseHeight - 1), Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0024); 62 3436092 : } 63 : 64 6558 : QvvecSyncModeMap GetEnabledQuorumVvecSyncEntries(const ArgsManager& args) 65 : { 66 6558 : QvvecSyncModeMap mapQuorumVvecSyncEntries; 67 6819 : for (const auto& strEntry : args.GetArgs("-llmq-qvvec-sync")) { 68 261 : Consensus::LLMQType llmqType = Consensus::LLMQType::LLMQ_NONE; 69 261 : QvvecSyncMode mode{QvvecSyncMode::Invalid}; 70 261 : std::istringstream ssEntry(strEntry); 71 261 : std::string strLLMQType, strMode, strTest; 72 261 : const bool fLLMQTypePresent = std::getline(ssEntry, strLLMQType, ':') && strLLMQType != ""; 73 261 : const bool fModePresent = std::getline(ssEntry, strMode, ':') && strMode != ""; 74 261 : const bool fTooManyEntries = static_cast<bool>(std::getline(ssEntry, strTest, ':')); 75 261 : if (!fLLMQTypePresent || !fModePresent || fTooManyEntries) { 76 24 : throw std::invalid_argument(strprintf("Invalid format in -llmq-qvvec-sync: %s", strEntry)); 77 : } 78 : 79 726 : if (auto optLLMQParams = util::find_if_opt(Params().GetConsensus().llmqs, [&strLLMQType](const auto& params) { 80 489 : return params.name == strLLMQType; 81 : })) { 82 228 : llmqType = optLLMQParams->type; 83 228 : } else { 84 9 : throw std::invalid_argument(strprintf("Invalid llmqType in -llmq-qvvec-sync: %s", strEntry)); 85 : } 86 228 : if (mapQuorumVvecSyncEntries.count(llmqType) > 0) { 87 3 : throw std::invalid_argument(strprintf("Duplicated llmqType in -llmq-qvvec-sync: %s", strEntry)); 88 : } 89 : 90 : int32_t nMode; 91 225 : if (ParseInt32(strMode, &nMode)) { 92 225 : switch (nMode) { 93 : case (int32_t)QvvecSyncMode::Always: 94 111 : mode = QvvecSyncMode::Always; 95 111 : break; 96 : case (int32_t)QvvecSyncMode::OnlyIfTypeMember: 97 108 : mode = QvvecSyncMode::OnlyIfTypeMember; 98 108 : break; 99 : default: 100 6 : mode = QvvecSyncMode::Invalid; 101 6 : break; 102 : } 103 225 : } 104 225 : if (mode == QvvecSyncMode::Invalid) { 105 6 : throw std::invalid_argument(strprintf("Invalid mode in -llmq-qvvec-sync: %s", strEntry)); 106 : } 107 219 : mapQuorumVvecSyncEntries.emplace(llmqType, mode); 108 261 : } 109 6516 : return mapQuorumVvecSyncEntries; 110 6600 : } 111 : 112 16126 : std::vector<Consensus::LLMQType> GetEnabledQuorumTypes(const ChainstateManager& chainman, 113 : gsl::not_null<const CBlockIndex*> pindex) 114 : { 115 16126 : std::vector<Consensus::LLMQType> ret; 116 16126 : ret.reserve(Params().GetConsensus().llmqs.size()); 117 96756 : for (const auto& params : Params().GetConsensus().llmqs) { 118 80630 : if (chainman.IsQuorumTypeEnabled(params.type, pindex)) { 119 50903 : ret.push_back(params.type); 120 50903 : } 121 : } 122 16126 : return ret; 123 16126 : } 124 : 125 399463 : std::vector<std::reference_wrapper<const Consensus::LLMQParams>> GetEnabledQuorumParams( 126 : const ChainstateManager& chainman, gsl::not_null<const CBlockIndex*> pindex) 127 : { 128 399463 : std::vector<std::reference_wrapper<const Consensus::LLMQParams>> ret; 129 399463 : ret.reserve(Params().GetConsensus().llmqs.size()); 130 : 131 399463 : std::copy_if(Params().GetConsensus().llmqs.begin(), Params().GetConsensus().llmqs.end(), std::back_inserter(ret), 132 2396778 : [&pindex, &chainman](const auto& params) { return chainman.IsQuorumTypeEnabled(params.type, pindex); }); 133 : 134 399463 : return ret; 135 399463 : } 136 : } // namespace llmq