From 94dea23036092d5aaf6b0b131eba16184f3601c6 Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Sat, 11 Jun 2022 07:26:02 +0300 Subject: [PATCH 1/5] docs(llmq): Improved documentation for keepOldConnections (#4876) --- src/llmq/params.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/llmq/params.h b/src/llmq/params.h index 9cb2afe6d3889..89482a2edf06a 100644 --- a/src/llmq/params.h +++ b/src/llmq/params.h @@ -90,8 +90,9 @@ struct LLMQParams { // Number of quorums to consider "active" for signing sessions int signingActiveQuorumCount; - // Used for intra-quorum communication. This is the number of quorums for which we should keep old connections. This - // should be at least one more then the active quorums set. + // Used for intra-quorum communication. This is the number of quorums for which we should keep old connections. + // For non-rotated quorums it should be at least one more than the active quorums set. + // For rotated quorums it should be equal to 2 x active quorums set. int keepOldConnections; // How many members should we try to send all sigShares to before we give up. From 567ba392bad2472174e48d0b1ce5778d035338bf Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Wed, 29 Jun 2022 03:14:09 +0300 Subject: [PATCH 2/5] fix: Faster feature_llmq_rotation.py + introduction of llmq_devnet_dip0024 (#4878) * Added LLMQ_DEVNET_V2 * Faster feature_llmq_rotation func test * Updated llmq_devnet_dip0024 * Adjusted parameters * Better comments * Re-adjusted rotated llmq params --- src/chainparams.cpp | 1 + src/llmq/params.h | 38 ++++++++++++++++++++---- src/llmq/utils.cpp | 4 +-- test/functional/feature_llmq_rotation.py | 25 +--------------- 4 files changed, 37 insertions(+), 31 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 962ddd03519aa..325c5aeae37d8 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -715,6 +715,7 @@ class CDevNetParams : public CChainParams { AddLLMQ(Consensus::LLMQType::LLMQ_400_85); AddLLMQ(Consensus::LLMQType::LLMQ_100_67); AddLLMQ(Consensus::LLMQType::LLMQ_DEVNET); + AddLLMQ(Consensus::LLMQType::LLMQ_DEVNET_DIP0024); consensus.llmqTypeChainLocks = Consensus::LLMQType::LLMQ_50_60; consensus.llmqTypeInstantSend = Consensus::LLMQType::LLMQ_50_60; consensus.llmqTypeDIP0024InstantSend = Consensus::LLMQType::LLMQ_60_75; diff --git a/src/llmq/params.h b/src/llmq/params.h index 89482a2edf06a..a289ea24e476e 100644 --- a/src/llmq/params.h +++ b/src/llmq/params.h @@ -24,14 +24,17 @@ enum class LLMQType : uint8_t { LLMQ_TEST = 100, // 3 members, 2 (66%) threshold, one per hour. Params might differ when -llmqtestparams is used // for devnets only - LLMQ_DEVNET = 101, // 10 members, 6 (60%) threshold, one per hour. Params might differ when -llmqdevnetparams is used + LLMQ_DEVNET = 101, // 12 members, 6 (50%) threshold, one per hour. Params might differ when -llmqdevnetparams is used // for testing activation of new quorums only LLMQ_TEST_V17 = 102, // 3 members, 2 (66%) threshold, one per hour. Params might differ when -llmqtestparams is used + // for testing only LLMQ_TEST_DIP0024 = 103, // 4 members, 2 (66%) threshold, one per hour. Params might differ when -llmqtestparams is used - LLMQ_TEST_INSTANTSEND = 104, // 3 members, 2 (66%) threshold, one per hour. Params might differ when -llmqtestinstantsendparams is used + + // for devnets only. rotated version (v2) for devnets + LLMQ_DEVNET_DIP0024 = 105 // 8 members, 4 (50%) threshold, one per hour. Params might differ when -llmqdevnetparams is used }; // Configures a LLMQ and its DKG @@ -100,7 +103,7 @@ struct LLMQParams { }; -static constexpr std::array available_llmqs = { +static constexpr std::array available_llmqs = { /** * llmq_test @@ -186,7 +189,7 @@ static constexpr std::array available_llmqs = { .minSize = 3, .threshold = 2, - .dkgInterval = 24, // one DKG per hour + .dkgInterval = 24, // DKG cycle .dkgPhaseBlocks = 2, .dkgMiningWindowStart = 10, // dkgPhaseBlocks * 5 = after finalization .dkgMiningWindowEnd = 18, @@ -222,6 +225,31 @@ static constexpr std::array available_llmqs = { .recoveryMembers = 6, }, + /** + * llmq_devnet_dip0024 + * This quorum is only used for testing on devnets + * + */ + LLMQParams{ + .type = LLMQType::LLMQ_DEVNET_DIP0024, + .name = "llmq_devnet_dip0024", + .useRotation = true, + .size = 8, + .minSize = 6, + .threshold = 4, + + .dkgInterval = 48, // DKG cycle + .dkgPhaseBlocks = 2, + .dkgMiningWindowStart = 12, // signingActiveQuorumCount + dkgPhaseBlocks * 5 = after finalization + .dkgMiningWindowEnd = 20, + .dkgBadVotesThreshold = 7, + + .signingActiveQuorumCount = 2, // just a few ones to allow easier testing + + .keepOldConnections = 4, + .recoveryMembers = 4, + }, + /** * llmq_50_60 * This quorum is deployed on mainnet and requires @@ -259,7 +287,7 @@ static constexpr std::array available_llmqs = { .minSize = 50, .threshold = 45, - .dkgInterval = 24 * 12, // one DKG every 12 hours + .dkgInterval = 24 * 12, // DKG cycle every 12 hours .dkgPhaseBlocks = 2, .dkgMiningWindowStart = 10, // dkgPhaseBlocks * 5 = after finalization .dkgMiningWindowEnd = 18, diff --git a/src/llmq/utils.cpp b/src/llmq/utils.cpp index 8f0414df99f8e..cd7b5c6e0b2a8 100644 --- a/src/llmq/utils.cpp +++ b/src/llmq/utils.cpp @@ -797,6 +797,7 @@ bool CLLMQUtils::IsQuorumTypeEnabledInternal(Consensus::LLMQType llmqType, const switch (llmqType) { case Consensus::LLMQType::LLMQ_TEST_INSTANTSEND: + case Consensus::LLMQType::LLMQ_DEVNET: case Consensus::LLMQType::LLMQ_50_60: { if (IsInstantSendLLMQTypeShared()) { break; @@ -823,6 +824,7 @@ bool CLLMQUtils::IsQuorumTypeEnabledInternal(Consensus::LLMQType llmqType, const } break; case Consensus::LLMQType::LLMQ_60_75: + case Consensus::LLMQType::LLMQ_DEVNET_DIP0024: case Consensus::LLMQType::LLMQ_TEST_DIP0024: { bool fDIP0024IsActive = optDIP0024IsActive.has_value() ? *optDIP0024IsActive : CLLMQUtils::IsDIP0024Active(pindex); if (!fDIP0024IsActive) { @@ -830,8 +832,6 @@ bool CLLMQUtils::IsQuorumTypeEnabledInternal(Consensus::LLMQType llmqType, const } break; } - case Consensus::LLMQType::LLMQ_DEVNET: - break; default: throw std::runtime_error(strprintf("%s: Unknown LLMQ type %d", __func__, static_cast(llmqType))); } diff --git a/test/functional/feature_llmq_rotation.py b/test/functional/feature_llmq_rotation.py index acb285ce69803..8d27b0eea4ef2 100755 --- a/test/functional/feature_llmq_rotation.py +++ b/test/functional/feature_llmq_rotation.py @@ -53,7 +53,7 @@ def getmnlistdiff(self, baseBlockHash, blockHash): class LLMQQuorumRotationTest(DashTestFramework): def set_test_params(self): - self.set_dash_test_params(16, 15, fast_dip3_enforcement=True) + self.set_dash_test_params(9, 8, fast_dip3_enforcement=True) self.set_dash_llmq_test_params(4, 4) def run_test(self): @@ -124,23 +124,6 @@ def run_test(self): expectedNew = [q_100_1, q_102_1, q_103_1_0, q_103_1_1] quorumList = self.test_getmnlistdiff_quorums(b_1, b_2, quorumList, expectedDeleted, expectedNew) - (quorum_info_2_0, quorum_info_2_1) = self.mine_cycle_quorum(llmq_type_name=llmq_type_name, llmq_type=llmq_type) - quorum_members_2_0 = extract_quorum_members(quorum_info_2_0) - quorum_members_2_1 = extract_quorum_members(quorum_info_2_1) - assert_equal(len(intersection(quorum_members_2_0, quorum_members_2_1)), 0) - self.log.info("Quorum #2_0 members: " + str(quorum_members_2_0)) - self.log.info("Quorum #2_1 members: " + str(quorum_members_2_1)) - - q_100_2 = QuorumId(100, int(quorum_info_2_0["quorumHash"], 16)) - q_102_2 = QuorumId(102, int(quorum_info_2_0["quorumHash"], 16)) - q_103_2_0 = QuorumId(103, int(quorum_info_2_0["quorumHash"], 16)) - q_103_2_1 = QuorumId(103, int(quorum_info_2_1["quorumHash"], 16)) - - b_3 = self.nodes[0].getbestblockhash() - expectedDeleted = [q_100_0, q_102_0, q_103_1_0, q_103_1_1] - expectedNew = [q_100_2, q_102_2, q_103_2_0, q_103_2_1] - quorumList = self.test_getmnlistdiff_quorums(b_2, b_3, quorumList, expectedDeleted, expectedNew) - mninfos_online = self.mninfo.copy() nodes = [self.nodes[0]] + [mn.node for mn in mninfos_online] sync_blocks(nodes) @@ -152,12 +135,6 @@ def run_test(self): assert_greater_than_or_equal(len(intersection(quorum_members_0_0, quorum_members_1_0)), 3) assert_greater_than_or_equal(len(intersection(quorum_members_0_1, quorum_members_1_1)), 3) - assert_greater_than_or_equal(len(intersection(quorum_members_0_0, quorum_members_2_0)), 2) - assert_greater_than_or_equal(len(intersection(quorum_members_0_1, quorum_members_2_1)), 2) - - assert_greater_than_or_equal(len(intersection(quorum_members_1_0, quorum_members_2_0)), 3) - assert_greater_than_or_equal(len(intersection(quorum_members_1_1, quorum_members_2_1)), 3) - self.log.info("Mine a quorum to invalidate") (quorum_info_3_0, quorum_info_3_1) = self.mine_cycle_quorum(llmq_type_name=llmq_type_name, llmq_type=llmq_type) From 2dcbedd6e2f06ed0ab4dee46dbf6d52af45227ec Mon Sep 17 00:00:00 2001 From: Nathan Marley Date: Tue, 14 Jun 2022 06:04:56 -0300 Subject: [PATCH 3/5] fix(gov): do not allow empty proposal names (#4883) * gov: Do not allow empty proposal names * Add test for invalid (empty) proposal name * Use pasta suggestion --- src/governance/validators.cpp | 5 +++++ src/test/data/proposals_invalid.json | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/governance/validators.cpp b/src/governance/validators.cpp index d062b18ff89b8..3be3778a187bf 100644 --- a/src/governance/validators.cpp +++ b/src/governance/validators.cpp @@ -99,6 +99,11 @@ bool CProposalValidator::ValidateName() return false; } + if (strName.empty()) { + strErrorMessages += "name cannot be empty;"; + return false; + } + static constexpr std::string_view strAllowedChars{"-_abcdefghijklmnopqrstuvwxyz0123456789"}; strName = ToLower(strName); diff --git a/src/test/data/proposals_invalid.json b/src/test/data/proposals_invalid.json index 79fa959c8b4ff..2159e7df1b021 100644 --- a/src/test/data/proposals_invalid.json +++ b/src/test/data/proposals_invalid.json @@ -16,5 +16,6 @@ {"end_epoch": 1491368400, "name": "dean-miller-5493", "payment_address": "XpG61qAVhdyN7AqVZQsHfJL7AEk4dPVinc", "payment_amount": "25.75", "start_epoch": 1474261086, "type": 1, "url": "http://dashcentral.org/dean-miller-5493"}, {"end_epoch": "1491368400", "name": "dean-miller-5493", "payment_address": "XpG61qAVhdyN7AqVZQsHfJL7AEk4dPVinc", "payment_amount": 25.75, "start_epoch": 1474261086, "type": 1, "url": "http://dashcentral.org/dean-miller-5493"}, {"end_epoch": 1491368400, "name": "dean-miller-5493", "payment_address": "XpG61qAVhdyN7AqVZQsHfJL7AEk4dPVinc", "payment_amount": 25.75, "start_epoch": "1474261086", "type": 1, "url": "http://dashcentral.org/dean-miller-5493"}, -{"end_epoch": 1491368400, "name": "dean-miller-5493", "payment_address": "XpG61qAVhdyN7AqVZQsHfJL7AEk4dPVinc", "payment_amount": 25.75, "start_epoch": 1474261086, "type": 2, "url": "http://dashcentral.org/dean-miller-5493"} +{"end_epoch": 1491368400, "name": "dean-miller-5493", "payment_address": "XpG61qAVhdyN7AqVZQsHfJL7AEk4dPVinc", "payment_amount": 25.75, "start_epoch": 1474261086, "type": 2, "url": "http://dashcentral.org/dean-miller-5493"}, +{"end_epoch": 1491368400, "name": "", "payment_address": "XpG61qAVhdyN7AqVZQsHfJL7AEk4dPVinc", "payment_amount": 25.75, "start_epoch": 1474261086, "type": 1, "url": "http://dashcentral.org/dean-miller-5493"} ] From 9b0222a01aaf6c3ecad93cc5dff4c1524fd993b8 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Mon, 27 Jun 2022 13:02:46 +0300 Subject: [PATCH 4/5] llmq: Various fixes and improvements (#4890) * feat(llmq): Introduce useRotation in LLMQParams * fix(llmq): Fix IsQuorumRotationEnabled to recognize all dip0024 quorums * fix(llmq): Do not allow rotation llmqs for `-llmqinstantsend` and non-rotation ones for `-llmqinstantsenddip0024` * fix(llmq): Unify and fix IsMiningPhase NOTE: no need for 1 extra block in mining phase for rotation quorums * chore(llmq): Reduce the number of IsQuorumRotationEnabled calls * chore(llmq): Improve logging * feat(llmq): Make `llmq-` threads for rotation quorums distinguishable by quorum index * fix(llmq): Fix another endless loop in GetQuorumRelayMembers * throw an error when a llmq type with an incompatible rotation flag is picked for `-llmq...` params * Add a note about loop conditions * llmq: Make TransactionRemovedFromMempool the last action for invalid txes, just like we do for orphans with rejected parents Write to log, send reject msg and (maybe) punish first and only then notify IS about the tx removal. Makes it easier to reason about it when reading logs. --- src/chainparams.cpp | 9 +++++++ src/llmq/blockprocessor.cpp | 45 +++++++++++++++------------------- src/llmq/dkgsessionhandler.cpp | 44 ++++++++++++++++----------------- src/llmq/params.h | 21 +++++++++++++--- src/llmq/utils.cpp | 12 ++++++--- src/net_processing.cpp | 2 +- src/rpc/rpcquorums.cpp | 7 +++--- 7 files changed, 81 insertions(+), 59 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 325c5aeae37d8..6f064512b21f1 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -1223,6 +1223,9 @@ void CDevNetParams::UpdateDevnetLLMQChainLocksFromArgs(const ArgsManager& args) Consensus::LLMQType llmqType = Consensus::LLMQType::LLMQ_NONE; for (const auto& params : consensus.llmqs) { if (params.name == strLLMQType) { + if (params.useRotation) { + throw std::runtime_error("LLMQ type specified for -llmqchainlocks must NOT use rotation"); + } llmqType = params.type; } } @@ -1242,6 +1245,9 @@ void CDevNetParams::UpdateDevnetLLMQInstantSendFromArgs(const ArgsManager& args) Consensus::LLMQType llmqType = Consensus::LLMQType::LLMQ_NONE; for (const auto& params : consensus.llmqs) { if (params.name == strLLMQType) { + if (params.useRotation) { + throw std::runtime_error("LLMQ type specified for -llmqinstantsend must NOT use rotation"); + } llmqType = params.type; } } @@ -1261,6 +1267,9 @@ void CDevNetParams::UpdateDevnetLLMQInstantSendDIP0024FromArgs(const ArgsManager Consensus::LLMQType llmqType = Consensus::LLMQType::LLMQ_NONE; for (const auto& params : consensus.llmqs) { if (params.name == strLLMQType) { + if (!params.useRotation) { + throw std::runtime_error("LLMQ type specified for -llmqinstantsenddip0024 must use rotation"); + } llmqType = params.type; } } diff --git a/src/llmq/blockprocessor.cpp b/src/llmq/blockprocessor.cpp index 2850aee9deddd..d1f8c690dabe8 100644 --- a/src/llmq/blockprocessor.cpp +++ b/src/llmq/blockprocessor.cpp @@ -252,7 +252,9 @@ bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockH return true; } - if (llmq::CLLMQUtils::IsQuorumRotationEnabled(llmq_params.type, pQuorumBaseBlockIndex)) { + bool rotation_enabled = CLLMQUtils::IsQuorumRotationEnabled(llmq_params.type, pQuorumBaseBlockIndex); + + if (rotation_enabled) { LogPrint(BCLog::LLMQ, "[ProcessCommitment] height[%d] pQuorumBaseBlockIndex[%d] quorumIndex[%d] qversion[%d] Built\n", nHeight, pQuorumBaseBlockIndex->nHeight, qc.quorumIndex, qc.nVersion); } @@ -261,7 +263,7 @@ bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockH auto cacheKey = std::make_pair(llmq_params.type, quorumHash); evoDb.Write(std::make_pair(DB_MINED_COMMITMENT, cacheKey), std::make_pair(qc, blockHash)); - if (llmq::CLLMQUtils::IsQuorumRotationEnabled(llmq_params.type, pQuorumBaseBlockIndex)) { + if (rotation_enabled) { evoDb.Write(BuildInversedHeightKeyIndexed(llmq_params.type, nHeight, int(qc.quorumIndex)), pQuorumBaseBlockIndex->nHeight); } else { evoDb.Write(BuildInversedHeightKey(llmq_params.type, nHeight), pQuorumBaseBlockIndex->nHeight); @@ -415,23 +417,16 @@ bool CQuorumBlockProcessor::IsMiningPhase(const Consensus::LLMQParams& llmqParam // Note: This function can be called for new blocks assert(nHeight <= ::ChainActive().Height() + 1); - const auto pindex = ::ChainActive().Height() < nHeight ? ::ChainActive().Tip() : ::ChainActive().Tip()->GetAncestor(nHeight); - if (CLLMQUtils::IsQuorumRotationEnabled(llmqParams.type, pindex)) { - int quorumCycleStartHeight = nHeight - (nHeight % llmqParams.dkgInterval); - int quorumCycleMiningStartHeight = quorumCycleStartHeight + llmqParams.signingActiveQuorumCount + (5 * llmqParams.dkgPhaseBlocks) + 1; - int quorumCycleMiningEndHeight = quorumCycleMiningStartHeight + (llmqParams.dkgMiningWindowEnd - llmqParams.dkgMiningWindowStart); - LogPrint(BCLog::LLMQ, "[IsMiningPhase] nHeight[%d] quorumCycleStartHeight[%d] -- mining[%d-%d]\n", nHeight, quorumCycleStartHeight, quorumCycleMiningStartHeight, quorumCycleMiningEndHeight); + int quorumCycleStartHeight = nHeight - (nHeight % llmqParams.dkgInterval); + int quorumCycleMiningStartHeight = quorumCycleStartHeight + llmqParams.dkgMiningWindowStart; + int quorumCycleMiningEndHeight = quorumCycleStartHeight + llmqParams.dkgMiningWindowEnd; - if (nHeight >= quorumCycleMiningStartHeight && nHeight <= quorumCycleMiningEndHeight) { - return true; - } - } else { - int phaseIndex = nHeight % llmqParams.dkgInterval; - if (phaseIndex >= llmqParams.dkgMiningWindowStart && phaseIndex <= llmqParams.dkgMiningWindowEnd) { - return true; - } + if (nHeight >= quorumCycleMiningStartHeight && nHeight <= quorumCycleMiningEndHeight) { + LogPrint(BCLog::LLMQ, "[IsMiningPhase] nHeight[%d] llmqType[%d] quorumCycleStartHeight[%d] -- mining[%d-%d]\n", nHeight, int(llmqParams.type), quorumCycleStartHeight, quorumCycleMiningStartHeight, quorumCycleMiningEndHeight); + return true; } + LogPrint(BCLog::LLMQ, "[IsMiningPhase] nHeight[%d] llmqType[%d] quorumCycleStartHeight[%d] -- NOT mining[%d-%d]\n", nHeight, int(llmqParams.type), quorumCycleStartHeight, quorumCycleMiningStartHeight, quorumCycleMiningEndHeight); return false; } @@ -446,13 +441,13 @@ bool CQuorumBlockProcessor::IsCommitmentRequired(const Consensus::LLMQParams& ll assert(nHeight <= ::ChainActive().Height() + 1); const auto pindex = ::ChainActive().Height() < nHeight ? ::ChainActive().Tip() : ::ChainActive().Tip()->GetAncestor(nHeight); - for (int quorumIndex = 0; quorumIndex < llmqParams.signingActiveQuorumCount; ++quorumIndex) { + bool rotation_enabled = CLLMQUtils::IsQuorumRotationEnabled(llmqParams.type, pindex); + size_t quorums_num = rotation_enabled ? llmqParams.signingActiveQuorumCount : 1; + + for (int quorumIndex = 0; quorumIndex < quorums_num; ++quorumIndex) { uint256 quorumHash = GetQuorumBlockHash(llmqParams, nHeight, quorumIndex); if (quorumHash.IsNull()) return false; if (HasMinedCommitment(llmqParams.type, quorumHash)) return false; - if (!CLLMQUtils::IsQuorumRotationEnabled(llmqParams.type, pindex)) { - break; - } } return true; @@ -725,8 +720,11 @@ std::optional> CQuorumBlockProcessor::GetMineableC assert(nHeight <= ::ChainActive().Height() + 1); const auto pindex = ::ChainActive().Height() < nHeight ? ::ChainActive().Tip() : ::ChainActive().Tip()->GetAncestor(nHeight); + bool rotation_enabled = CLLMQUtils::IsQuorumRotationEnabled(llmqParams.type, pindex); + size_t quorums_num = rotation_enabled ? llmqParams.signingActiveQuorumCount : 1; + std::stringstream ss; - for (int quorumIndex = 0; quorumIndex < llmqParams.signingActiveQuorumCount; ++quorumIndex) { + for (int quorumIndex = 0; quorumIndex < quorums_num; ++quorumIndex) { CFinalCommitment cf; uint256 quorumHash = GetQuorumBlockHash(llmqParams, nHeight, quorumIndex); @@ -742,7 +740,7 @@ std::optional> CQuorumBlockProcessor::GetMineableC // null commitment required cf = CFinalCommitment(llmqParams, quorumHash); cf.quorumIndex = static_cast(quorumIndex); - if (CLLMQUtils::IsQuorumRotationEnabled(llmqParams.type, pindex)) { + if (rotation_enabled) { cf.nVersion = CFinalCommitment::INDEXED_QUORUM_VERSION; } ss << "{ created nversion[" << cf.nVersion << "] quorumIndex[" << cf.quorumIndex << "] }"; @@ -752,9 +750,6 @@ std::optional> CQuorumBlockProcessor::GetMineableC } ret.push_back(std::move(cf)); - if (!CLLMQUtils::IsQuorumRotationEnabled(llmqParams.type, pindex)) { - break; - } } LogPrint(BCLog::LLMQ, "GetMineableCommitments cf height[%d] content: %s\n", nHeight, ss.str()); diff --git a/src/llmq/dkgsessionhandler.cpp b/src/llmq/dkgsessionhandler.cpp index c1df8b41bfdc9..d268e81d90fc4 100644 --- a/src/llmq/dkgsessionhandler.cpp +++ b/src/llmq/dkgsessionhandler.cpp @@ -102,7 +102,7 @@ void CDKGSessionHandler::UpdatedBlockTip(const CBlockIndex* pindexNew) phase = static_cast(phaseInt); } - LogPrint(BCLog::LLMQ_DKG, "CDKGSessionHandler::%s -- %s - quorumIndex=%d, currentHeight=%d, pQuorumBaseBlockIndex->nHeight=%d, oldPhase=%d, newPhase=%d\n", __func__, + LogPrint(BCLog::LLMQ_DKG, "CDKGSessionHandler::%s -- %s qi[%d] currentHeight=%d, pQuorumBaseBlockIndex->nHeight=%d, oldPhase=%d, newPhase=%d\n", __func__, params.name, quorumIndex, currentHeight, pQuorumBaseBlockIndex->nHeight, int(oldPhase), int(phase)); } @@ -126,7 +126,7 @@ void CDKGSessionHandler::StartThread() throw std::runtime_error("Tried to start an already started CDKGSessionHandler thread."); } - std::string threadName = strprintf("llmq-%d", (uint8_t)params.type); + std::string threadName = strprintf("llmq-%d-%d", (uint8_t)params.type, quorumIndex); phaseHandlerThread = std::thread(&TraceThread >, threadName, std::function(std::bind(&CDKGSessionHandler::PhaseHandlerThread, this))); } @@ -148,10 +148,10 @@ bool CDKGSessionHandler::InitNewQuorum(const CBlockIndex* pQuorumBaseBlockIndex) auto mns = CLLMQUtils::GetAllQuorumMembers(params.type, pQuorumBaseBlockIndex); if (!curSession->Init(pQuorumBaseBlockIndex, mns, WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash), quorumIndex)) { - LogPrintf("CDKGSessionManager::%s -- height[%d] quorum initialization failed for %s mns[%d]\n", __func__, pQuorumBaseBlockIndex->nHeight, curSession->params.name, mns.size()); + LogPrintf("CDKGSessionManager::%s -- height[%d] quorum initialization failed for %s qi[%d] mns[%d]\n", __func__, pQuorumBaseBlockIndex->nHeight, curSession->params.name, quorumIndex, mns.size()); return false; } else { - LogPrintf("CDKGSessionManager::%s -- height[%d] quorum initialization OK for %s\n", __func__, pQuorumBaseBlockIndex->nHeight, curSession->params.name); + LogPrintf("CDKGSessionManager::%s -- height[%d] quorum initialization OK for %s qi[%d]\n", __func__, pQuorumBaseBlockIndex->nHeight, curSession->params.name, quorumIndex); } return true; @@ -171,23 +171,23 @@ void CDKGSessionHandler::WaitForNextPhase(std::optional curPhase, const uint256& expectedQuorumHash, const WhileWaitFunc& shouldNotWait) const { - LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - starting, curPhase=%d, nextPhase=%d\n", __func__, params.name, curPhase.has_value() ? int(*curPhase) : -1, int(nextPhase)); + LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - starting, curPhase=%d, nextPhase=%d\n", __func__, params.name, quorumIndex, curPhase.has_value() ? int(*curPhase) : -1, int(nextPhase)); while (true) { if (stopRequested) { - LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - aborting due to stop/shutdown requested\n", __func__, params.name); + LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - aborting due to stop/shutdown requested\n", __func__, params.name, quorumIndex); throw AbortPhaseException(); } auto [_phase, _quorumHash] = GetPhaseAndQuorumHash(); if (!expectedQuorumHash.IsNull() && _quorumHash != expectedQuorumHash) { - LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - aborting due unexpected expectedQuorumHash change\n", __func__, params.name); + LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - aborting due unexpected expectedQuorumHash change\n", __func__, params.name, quorumIndex); throw AbortPhaseException(); } if (_phase == nextPhase) { break; } if (curPhase.has_value() && _phase != curPhase) { - LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - aborting due unexpected phase change\n", __func__, params.name); + LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - aborting due unexpected phase change, _phase=%d, curPhase=%d\n", __func__, params.name, quorumIndex, int(_phase), curPhase.has_value() ? int(*curPhase) : -1); throw AbortPhaseException(); } if (!shouldNotWait()) { @@ -195,7 +195,7 @@ void CDKGSessionHandler::WaitForNextPhase(std::optional curPhase, } } - LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - done, curPhase=%d, nextPhase=%d\n", __func__, params.name, curPhase.has_value() ? int(*curPhase) : -1, int(nextPhase)); + LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - done, curPhase=%d, nextPhase=%d\n", __func__, params.name, quorumIndex, curPhase.has_value() ? int(*curPhase) : -1, int(nextPhase)); if (nextPhase == QuorumPhase::Initialized) { quorumDKGDebugManager->ResetLocalSessionStatus(params.type, quorumIndex); @@ -210,21 +210,21 @@ void CDKGSessionHandler::WaitForNextPhase(std::optional curPhase, void CDKGSessionHandler::WaitForNewQuorum(const uint256& oldQuorumHash) const { - LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - starting\n", __func__, params.name); + LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d]- starting\n", __func__, params.name, quorumIndex); while (true) { if (stopRequested) { - LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - aborting due to stop/shutdown requested\n", __func__, params.name); + LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - aborting due to stop/shutdown requested\n", __func__, params.name, quorumIndex); throw AbortPhaseException(); } - auto p = GetPhaseAndQuorumHash(); - if (p.second != oldQuorumHash) { + auto [_, _quorumHash] = GetPhaseAndQuorumHash(); + if (_quorumHash != oldQuorumHash) { break; } UninterruptibleSleep(std::chrono::milliseconds{100}); } - LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - done\n", __func__, params.name); + LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - done\n", __func__, params.name, quorumIndex); } // Sleep some time to not fully overload the whole network @@ -263,11 +263,11 @@ void CDKGSessionHandler::SleepBeforePhase(QuorumPhase curPhase, heightTmp = heightStart = currentHeight; } - LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - starting sleep for %d ms, curPhase=%d\n", __func__, params.name, sleepTime, int(curPhase)); + LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - starting sleep for %d ms, curPhase=%d\n", __func__, params.name, quorumIndex, sleepTime, int(curPhase)); while (GetTimeMillis() < endTime) { if (stopRequested) { - LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - aborting due to stop/shutdown requested\n", __func__, params.name); + LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - aborting due to stop/shutdown requested\n", __func__, params.name, quorumIndex); throw AbortPhaseException(); } { @@ -283,7 +283,7 @@ void CDKGSessionHandler::SleepBeforePhase(QuorumPhase curPhase, } if (phase != curPhase || quorumHash != expectedQuorumHash) { // Something went wrong and/or we missed quite a few blocks and it's just too late now - LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - aborting due unexpected phase/expectedQuorumHash change\n", __func__, params.name); + LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - aborting due unexpected phase/expectedQuorumHash change\n", __func__, params.name, quorumIndex); throw AbortPhaseException(); } } @@ -292,7 +292,7 @@ void CDKGSessionHandler::SleepBeforePhase(QuorumPhase curPhase, } } - LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - done, curPhase=%d\n", __func__, params.name, int(curPhase)); + LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - done, curPhase=%d\n", __func__, params.name, quorumIndex, int(curPhase)); } void CDKGSessionHandler::HandlePhase(QuorumPhase curPhase, @@ -302,13 +302,13 @@ void CDKGSessionHandler::HandlePhase(QuorumPhase curPhase, const StartPhaseFunc& startPhaseFunc, const WhileWaitFunc& runWhileWaiting) { - LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - starting, curPhase=%d, nextPhase=%d\n", __func__, params.name, int(curPhase), int(nextPhase)); + LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - starting, curPhase=%d, nextPhase=%d\n", __func__, params.name, quorumIndex, int(curPhase), int(nextPhase)); SleepBeforePhase(curPhase, expectedQuorumHash, randomSleepFactor, runWhileWaiting); startPhaseFunc(); WaitForNextPhase(curPhase, nextPhase, expectedQuorumHash, runWhileWaiting); - LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - done, curPhase=%d, nextPhase=%d\n", __func__, params.name, int(curPhase), int(nextPhase)); + LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - done, curPhase=%d, nextPhase=%d\n", __func__, params.name, quorumIndex, int(curPhase), int(nextPhase)); } // returns a set of NodeIds which sent invalid messages @@ -543,14 +543,14 @@ void CDKGSessionHandler::PhaseHandlerThread() { while (!stopRequested) { try { - LogPrint(BCLog::LLMQ_DKG, "CDKGSessionHandler::%s -- %s - starting HandleDKGRound\n", __func__, params.name); + LogPrint(BCLog::LLMQ_DKG, "CDKGSessionHandler::%s -- %s qi[%d] - starting HandleDKGRound\n", __func__, params.name, quorumIndex); HandleDKGRound(); } catch (AbortPhaseException& e) { quorumDKGDebugManager->UpdateLocalSessionStatus(params.type, quorumIndex, [&](CDKGDebugSessionStatus& status) { status.aborted = true; return true; }); - LogPrint(BCLog::LLMQ_DKG, "CDKGSessionHandler::%s -- %s - aborted current DKG session\n", __func__, params.name); + LogPrint(BCLog::LLMQ_DKG, "CDKGSessionHandler::%s -- %s qi[%d] - aborted current DKG session\n", __func__, params.name, quorumIndex); } } } diff --git a/src/llmq/params.h b/src/llmq/params.h index a289ea24e476e..1a2d9029071b5 100644 --- a/src/llmq/params.h +++ b/src/llmq/params.h @@ -45,6 +45,9 @@ struct LLMQParams { // not consensus critical, only used in logging, RPC and UI std::string_view name; + // Whether this is a DIP0024 quorum or not + bool useRotation; + // the size of the quorum, e.g. 50 or 400 int size; @@ -113,6 +116,7 @@ static constexpr std::array available_llmqs = { LLMQParams{ .type = LLMQType::LLMQ_TEST, .name = "llmq_test", + .useRotation = false, .size = 3, .minSize = 2, .threshold = 2, @@ -137,6 +141,7 @@ static constexpr std::array available_llmqs = { LLMQParams{ .type = LLMQType::LLMQ_TEST_INSTANTSEND, .name = "llmq_test_instantsend", + .useRotation = false, .size = 3, .minSize = 2, .threshold = 2, @@ -161,6 +166,7 @@ static constexpr std::array available_llmqs = { LLMQParams{ .type = LLMQType::LLMQ_TEST_V17, .name = "llmq_test_v17", + .useRotation = false, .size = 3, .minSize = 2, .threshold = 2, @@ -185,14 +191,15 @@ static constexpr std::array available_llmqs = { LLMQParams{ .type = LLMQType::LLMQ_TEST_DIP0024, .name = "llmq_test_dip0024", + .useRotation = true, .size = 4, .minSize = 3, .threshold = 2, .dkgInterval = 24, // DKG cycle .dkgPhaseBlocks = 2, - .dkgMiningWindowStart = 10, // dkgPhaseBlocks * 5 = after finalization - .dkgMiningWindowEnd = 18, + .dkgMiningWindowStart = 12, // signingActiveQuorumCount + dkgPhaseBlocks * 5 = after finalization + .dkgMiningWindowEnd = 20, .dkgBadVotesThreshold = 2, .signingActiveQuorumCount = 2, // just a few ones to allow easier testing @@ -209,6 +216,7 @@ static constexpr std::array available_llmqs = { LLMQParams{ .type = LLMQType::LLMQ_DEVNET, .name = "llmq_devnet", + .useRotation = false, .size = 12, .minSize = 7, .threshold = 6, @@ -259,6 +267,7 @@ static constexpr std::array available_llmqs = { LLMQParams{ .type = LLMQType::LLMQ_50_60, .name = "llmq_50_60", + .useRotation = false, .size = 50, .minSize = 40, .threshold = 30, @@ -283,14 +292,15 @@ static constexpr std::array available_llmqs = { LLMQParams{ .type = LLMQType::LLMQ_60_75, .name = "llmq_60_75", + .useRotation = true, .size = 60, .minSize = 50, .threshold = 45, .dkgInterval = 24 * 12, // DKG cycle every 12 hours .dkgPhaseBlocks = 2, - .dkgMiningWindowStart = 10, // dkgPhaseBlocks * 5 = after finalization - .dkgMiningWindowEnd = 18, + .dkgMiningWindowStart = 42, // signingActiveQuorumCount + dkgPhaseBlocks * 5 = after finalization + .dkgMiningWindowEnd = 50, .dkgBadVotesThreshold = 48, .signingActiveQuorumCount = 32, @@ -307,6 +317,7 @@ static constexpr std::array available_llmqs = { LLMQParams{ .type = LLMQType::LLMQ_400_60, .name = "llmq_400_60", + .useRotation = false, .size = 400, .minSize = 300, .threshold = 240, @@ -333,6 +344,7 @@ static constexpr std::array available_llmqs = { LLMQParams{ .type = LLMQType::LLMQ_400_85, .name = "llmq_400_85", + .useRotation = false, .size = 400, .minSize = 350, .threshold = 340, @@ -359,6 +371,7 @@ static constexpr std::array available_llmqs = { LLMQParams{ .type = LLMQType::LLMQ_100_67, .name = "llmq_100_67", + .useRotation = false, .size = 100, .minSize = 80, .threshold = 67, diff --git a/src/llmq/utils.cpp b/src/llmq/utils.cpp index cd7b5c6e0b2a8..6f40b551d8bb4 100644 --- a/src/llmq/utils.cpp +++ b/src/llmq/utils.cpp @@ -534,7 +534,7 @@ bool CLLMQUtils::IsQuorumRotationEnabled(Consensus::LLMQType llmqType, const CBl { assert(pindex); - if (llmqType != Params().GetConsensus().llmqTypeDIP0024InstantSend) { + if (!GetLLMQParams(llmqType).useRotation) { return false; } @@ -646,13 +646,19 @@ std::set CLLMQUtils::GetQuorumRelayMembers(const Consensus::LLMQParams& int k = 0; while ((gap_max >>= 1) || k <= 1) { size_t idx = (i + gap) % mns.size(); + // It doesn't matter if this node is going to be added to the resulting set or not, + // we should always bump the gap and the k (step count) regardless. + // Refusing to bump the gap results in an incomplete set in the best case scenario + // (idx won't ever change again once we hit `==`). Not bumping k guarantees an endless + // loop when the first or the second node we check is the one that should be skipped + // (k <= 1 forever). + gap <<= 1; + k++; const auto& otherDmn = mns[idx]; if (otherDmn->proTxHash == proTxHash) { continue; } r.emplace(otherDmn->proTxHash); - gap <<= 1; - k++; } return r; }; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 7781b9f0b9ff8..d53c0138b4172 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -3312,7 +3312,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStrea LogPrintf("Not relaying invalid transaction %s from whitelisted peer=%d (%s)\n", tx.GetHash().ToString(), pfrom->GetId(), FormatStateMessage(state)); } } - llmq::quorumInstantSendManager->TransactionRemovedFromMempool(ptx); } // If a tx has been detected by recentRejects, we will have reached @@ -3345,6 +3344,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStrea if (nDoS > 0) { Misbehaving(pfrom->GetId(), nDoS); } + llmq::quorumInstantSendManager->TransactionRemovedFromMempool(ptx); } return true; } diff --git a/src/rpc/rpcquorums.cpp b/src/rpc/rpcquorums.cpp index 53fa8c9fc9b01..0421ba313a0cd 100644 --- a/src/rpc/rpcquorums.cpp +++ b/src/rpc/rpcquorums.cpp @@ -198,8 +198,10 @@ static UniValue quorum_dkgstatus(const JSONRPCRequest& request) UniValue quorumArrConnections(UniValue::VARR); for (const auto& type : llmq::CLLMQUtils::GetEnabledQuorumTypes(pindexTip)) { const auto& llmq_params = llmq::GetLLMQParams(type); + bool rotation_enabled = llmq::CLLMQUtils::IsQuorumRotationEnabled(type, pindexTip); + size_t quorums_num = rotation_enabled ? llmq_params.signingActiveQuorumCount : 1; - for (int quorumIndex = 0; quorumIndex < llmq_params.signingActiveQuorumCount; ++quorumIndex) { + for (int quorumIndex = 0; quorumIndex < quorums_num; ++quorumIndex) { UniValue obj(UniValue::VOBJ); obj.pushKV("llmqType", std::string(llmq_params.name)); obj.pushKV("quorumIndex", quorumIndex); @@ -241,9 +243,6 @@ static UniValue quorum_dkgstatus(const JSONRPCRequest& request) } } quorumArrConnections.push_back(obj); - if (!llmq::CLLMQUtils::IsQuorumRotationEnabled(type, pindexTip)) { - break; - } } LOCK(cs_main); From 7c8ce7019a792b4591e797bbaf8d4eb07ddb0d2d Mon Sep 17 00:00:00 2001 From: pasta Date: Tue, 28 Jun 2022 19:19:54 -0500 Subject: [PATCH 5/5] chore: bump to rc7 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 3e1d8423725f1..f6082404f77d1 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ([2.69]) define(_CLIENT_VERSION_MAJOR, 18) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_BUILD, 0) -define(_CLIENT_VERSION_RC, 6) +define(_CLIENT_VERSION_RC, 7) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2022) define(_COPYRIGHT_HOLDERS,[The %s developers])