From 406d20299d18d4b1cac0191349610f5c3a681c19 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Sun, 26 Nov 2023 02:36:55 +0300 Subject: [PATCH 01/10] fix: shift `CleanupOldQuorumData` to a block height with no DKGs around --- src/llmq/quorums.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 67b464770b3b..b53376d5ac79 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -998,7 +998,7 @@ static void DataCleanupHelper(CDBWrapper& db, std::set skip_list) void CQuorumManager::CleanupOldQuorumData(const CBlockIndex* pIndex) const { - if (!fMasternodeMode || pIndex == nullptr || (pIndex->nHeight % 576 != 0)) { + if (!fMasternodeMode || pIndex == nullptr || (pIndex->nHeight % 576 != 58 /* no DKGs running or to be started soon */)) { return; } From 9e9711df98851ab0728e0fc4caf7ef14ca85597a Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Sun, 26 Nov 2023 02:41:34 +0300 Subject: [PATCH 02/10] fix: avoid slow `CompactFull()` on cleanups --- src/llmq/quorums.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index b53376d5ac79..e7e8005e412c 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -955,7 +955,7 @@ void CQuorumManager::StartQuorumDataRecoveryThread(const CQuorumCPtr pQuorum, co }); } -static void DataCleanupHelper(CDBWrapper& db, std::set skip_list) +static void DataCleanupHelper(CDBWrapper& db, std::set skip_list, bool compact = false) { const auto prefixes = {DB_QUORUM_QUORUM_VVEC, DB_QUORUM_SK_SHARE}; @@ -993,7 +993,13 @@ static void DataCleanupHelper(CDBWrapper& db, std::set skip_list) } pcursor.reset(); - db.CompactFull(); + + if (compact) { + // Avoid using this on regular cleanups, use on db migrations only + LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- compact start\n", __func__); + db.CompactFull(); + LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- compact end\n", __func__); + } } void CQuorumManager::CleanupOldQuorumData(const CBlockIndex* pIndex) const From 698b6f45a7d6c34d818d972ea3bdb6ccd986f848 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Sun, 26 Nov 2023 03:56:42 +0300 Subject: [PATCH 03/10] fix: log format --- src/llmq/quorums.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index e7e8005e412c..d794cf51953c 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -989,7 +989,7 @@ static void DataCleanupHelper(CDBWrapper& db, std::set skip_list, bool db.WriteBatch(batch); - LogPrint(BCLog::LLMQ, "CQuorumManager::%d -- %s removed %d\n", __func__, prefix, count); + LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- %s removed %d\n", __func__, prefix, count); } pcursor.reset(); From d9531121fb7bad5bbb036a072d6a91e2f6b50dc8 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Sun, 26 Nov 2023 02:41:58 +0300 Subject: [PATCH 04/10] fix: extend cache size for platform quorums --- src/llmq/quorums.cpp | 1 + src/llmq/utils.cpp | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index d794cf51953c..47c977125c0f 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -1015,6 +1015,7 @@ void CQuorumManager::CleanupOldQuorumData(const CBlockIndex* pIndex) const // Unlike for other quorum types we want to keep data (secret key shares and vvec) // for Platform quorums for at least 2 months because Platform can be restarted and // it must be able to re-sign stuff. During a month, 24 * 30 quorums are created. + // NOTE: when changing this make sure to update InitQuorumsCache() accordingly constexpr auto numPlatformQuorumsDataToKeep = 24 * 30 * 2; for (const auto& params : Params().GetConsensus().llmqs) { diff --git a/src/llmq/utils.cpp b/src/llmq/utils.cpp index 9e3bc56a09aa..e3685764dc61 100644 --- a/src/llmq/utils.cpp +++ b/src/llmq/utils.cpp @@ -1087,9 +1087,13 @@ std::map GetEnabledQuorumVvecSyncEntries() template void InitQuorumsCache(CacheType& cache) { + // NOTE: See CQuorumManager::CleanupOldQuorumData() for more info + constexpr auto numPlatformQuorumsDataToKeep = 24 * 30 * 2; + const auto llmqTypePlatform = Params().GetConsensus().llmqTypePlatform; for (const auto& llmq : Params().GetConsensus().llmqs) { + const auto nQuorumsToKeep = llmq.type == llmqTypePlatform ? numPlatformQuorumsDataToKeep : llmq.keepOldConnections; cache.emplace(std::piecewise_construct, std::forward_as_tuple(llmq.type), - std::forward_as_tuple(llmq.keepOldConnections)); + std::forward_as_tuple(nQuorumsToKeep)); } } template void InitQuorumsCache>>(std::map>& cache); From 0b801c670ffe85e9c61e74078321b4224ff34dcd Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Sun, 26 Nov 2023 04:34:30 +0300 Subject: [PATCH 05/10] fix: run old quorum data cleanup in a separate thread --- src/llmq/quorums.cpp | 46 +++++++++++++++++++++++++++----------------- src/llmq/quorums.h | 2 +- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 47c977125c0f..b49746b0531b 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -296,7 +296,7 @@ void CQuorumManager::UpdatedBlockTip(const CBlockIndex* pindexNew, bool fInitial } TriggerQuorumDataRecoveryThreads(pindexNew); - CleanupOldQuorumData(pindexNew); + StartCleanupOldQuorumDataThread(pindexNew); } void CQuorumManager::CheckQuorumConnections(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pindexNew) const @@ -1002,33 +1002,43 @@ static void DataCleanupHelper(CDBWrapper& db, std::set skip_list, bool } } -void CQuorumManager::CleanupOldQuorumData(const CBlockIndex* pIndex) const +void CQuorumManager::StartCleanupOldQuorumDataThread(const CBlockIndex* pIndex) const { if (!fMasternodeMode || pIndex == nullptr || (pIndex->nHeight % 576 != 58 /* no DKGs running or to be started soon */)) { return; } - std::set dbKeysToSkip; + cxxtimer::Timer t(true); + LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- start\n", __func__); - LogPrint(BCLog::LLMQ, "CQuorumManager::%d -- start\n", __func__); - // Platform quorums in all networks are created every 24 blocks (~1h). - // Unlike for other quorum types we want to keep data (secret key shares and vvec) - // for Platform quorums for at least 2 months because Platform can be restarted and - // it must be able to re-sign stuff. During a month, 24 * 30 quorums are created. - // NOTE: when changing this make sure to update InitQuorumsCache() accordingly - constexpr auto numPlatformQuorumsDataToKeep = 24 * 30 * 2; + // do not block the caller thread + workerPool.push([pIndex, t, this](int threadId) { + std::set dbKeysToSkip; - for (const auto& params : Params().GetConsensus().llmqs) { - auto nQuorumsToKeep = params.type == Params().GetConsensus().llmqTypePlatform ? numPlatformQuorumsDataToKeep : params.keepOldConnections; - const auto vecQuorums = ScanQuorums(params.type, pIndex, nQuorumsToKeep); - for (const auto& pQuorum : vecQuorums) { - dbKeysToSkip.insert(MakeQuorumKey(*pQuorum)); + // Platform quorums in all networks are created every 24 blocks (~1h). + // Unlike for other quorum types we want to keep data (secret key shares and vvec) + // for Platform quorums for at least 2 months because Platform can be restarted and + // it must be able to re-sign stuff. During a month, 24 * 30 quorums are created. + constexpr auto numPlatformQuorumsDataToKeep = 24 * 30 * 2; + // NOTE: when changing this make sure to update InitQuorumsCache() accordingly + + for (const auto& params : Params().GetConsensus().llmqs) { + if (quorumThreadInterrupt) { + break; + } + auto nQuorumsToKeep = params.type == Params().GetConsensus().llmqTypePlatform ? numPlatformQuorumsDataToKeep : params.keepOldConnections; + const auto vecQuorums = ScanQuorums(params.type, pIndex, nQuorumsToKeep); + for (const auto& pQuorum : vecQuorums) { + dbKeysToSkip.insert(MakeQuorumKey(*pQuorum)); + } } - } - DataCleanupHelper(m_evoDb.GetRawDB(), dbKeysToSkip); + if (!quorumThreadInterrupt) { + DataCleanupHelper(m_evoDb.GetRawDB(), dbKeysToSkip); + } - LogPrint(BCLog::LLMQ, "CQuorumManager::%d -- done\n", __func__); + LogPrint(BCLog::LLMQ, "CQuorumManager::StartCleanupOldQuorumDataThread -- done. time=%d\n", t.count()); + }); } } // namespace llmq diff --git a/src/llmq/quorums.h b/src/llmq/quorums.h index bc2eba6ae425..976ba0f30078 100644 --- a/src/llmq/quorums.h +++ b/src/llmq/quorums.h @@ -277,7 +277,7 @@ class CQuorumManager void StartCachePopulatorThread(const CQuorumCPtr pQuorum) const; void StartQuorumDataRecoveryThread(const CQuorumCPtr pQuorum, const CBlockIndex* pIndex, uint16_t nDataMask) const; - void CleanupOldQuorumData(const CBlockIndex* pIndex) const; + void StartCleanupOldQuorumDataThread(const CBlockIndex* pIndex) const; }; extern std::unique_ptr quorumManager; From 05a9b7fa7f65b314253b26446c056ccd2e1fa3fe Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Sun, 26 Nov 2023 18:22:31 +0300 Subject: [PATCH 06/10] refactor: Introduce keepOldKeys to decouple the number of connections and the number of keys to keep --- src/llmq/params.h | 21 +++++++++++++++++++++ src/llmq/quorums.cpp | 10 +--------- src/llmq/utils.cpp | 6 +----- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/llmq/params.h b/src/llmq/params.h index 3076674fdb9e..a9cb118929f7 100644 --- a/src/llmq/params.h +++ b/src/llmq/params.h @@ -104,6 +104,13 @@ struct LLMQParams { // For rotated quorums it should be equal to 2 x active quorums set. int keepOldConnections; + // The number of quorums for which we should keep keys. Usually it's equal to keepOldConnections. + // Unlike for other quorum types we want to keep data (secret key shares and vvec) + // for Platform quorums for much longer because Platform can be restarted and + // it must be able to re-sign stuff. + + int keepOldKeys; + // How many members should we try to send all sigShares to before we give up. int recoveryMembers; }; @@ -138,6 +145,7 @@ static constexpr std::array available_llmqs = { .signingActiveQuorumCount = 2, // just a few ones to allow easier testing .keepOldConnections = 3, + .keepOldKeys = 3, .recoveryMembers = 3, }, @@ -163,6 +171,7 @@ static constexpr std::array available_llmqs = { .signingActiveQuorumCount = 2, // just a few ones to allow easier testing .keepOldConnections = 3, + .keepOldKeys = 3, .recoveryMembers = 3, }, @@ -188,6 +197,7 @@ static constexpr std::array available_llmqs = { .signingActiveQuorumCount = 2, // just a few ones to allow easier testing .keepOldConnections = 3, + .keepOldKeys = 3, .recoveryMembers = 3, }, @@ -213,6 +223,7 @@ static constexpr std::array available_llmqs = { .signingActiveQuorumCount = 2, // just a few ones to allow easier testing .keepOldConnections = 4, + .keepOldKeys = 4, .recoveryMembers = 3, }, @@ -238,6 +249,7 @@ static constexpr std::array available_llmqs = { .signingActiveQuorumCount = 2, // just a few ones to allow easier testing .keepOldConnections = 4, + .keepOldKeys = 24 * 30 * 2, // 2 months of quorums .recoveryMembers = 3, }, @@ -263,6 +275,7 @@ static constexpr std::array available_llmqs = { .signingActiveQuorumCount = 4, // just a few ones to allow easier testing .keepOldConnections = 5, + .keepOldKeys = 5, .recoveryMembers = 6, }, @@ -288,6 +301,7 @@ static constexpr std::array available_llmqs = { .signingActiveQuorumCount = 2, // just a few ones to allow easier testing .keepOldConnections = 4, + .keepOldKeys = 4, .recoveryMembers = 4, }, @@ -313,6 +327,7 @@ static constexpr std::array available_llmqs = { .signingActiveQuorumCount = 4, // just a few ones to allow easier testing .keepOldConnections = 5, + .keepOldKeys = 24 * 30 * 2, // 2 months of quorums .recoveryMembers = 6, }, @@ -338,6 +353,7 @@ static constexpr std::array available_llmqs = { .signingActiveQuorumCount = 24, // a full day worth of LLMQs .keepOldConnections = 25, + .keepOldKeys = 25, .recoveryMembers = 25, }, @@ -363,6 +379,7 @@ static constexpr std::array available_llmqs = { .signingActiveQuorumCount = 32, .keepOldConnections = 64, + .keepOldKeys = 64, .recoveryMembers = 25, }, @@ -389,6 +406,7 @@ static constexpr std::array available_llmqs = { .signingActiveQuorumCount = 4, // two days worth of LLMQs .keepOldConnections = 5, + .keepOldKeys = 5, .recoveryMembers = 100, }, @@ -416,6 +434,7 @@ static constexpr std::array available_llmqs = { .signingActiveQuorumCount = 4, // four days worth of LLMQs .keepOldConnections = 5, + .keepOldKeys = 5, .recoveryMembers = 100, }, @@ -443,6 +462,7 @@ static constexpr std::array available_llmqs = { .signingActiveQuorumCount = 24, // a full day worth of LLMQs .keepOldConnections = 25, + .keepOldKeys = 24 * 30 * 2, // 2 months of quorums .recoveryMembers = 50, }, @@ -470,6 +490,7 @@ static constexpr std::array available_llmqs = { .signingActiveQuorumCount = 24, // a full day worth of LLMQs .keepOldConnections = 25, + .keepOldKeys = 24 * 30 * 2, // 2 months of quorums .recoveryMembers = 12, }, diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index b49746b0531b..0b1e7f69223b 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -1015,19 +1015,11 @@ void CQuorumManager::StartCleanupOldQuorumDataThread(const CBlockIndex* pIndex) workerPool.push([pIndex, t, this](int threadId) { std::set dbKeysToSkip; - // Platform quorums in all networks are created every 24 blocks (~1h). - // Unlike for other quorum types we want to keep data (secret key shares and vvec) - // for Platform quorums for at least 2 months because Platform can be restarted and - // it must be able to re-sign stuff. During a month, 24 * 30 quorums are created. - constexpr auto numPlatformQuorumsDataToKeep = 24 * 30 * 2; - // NOTE: when changing this make sure to update InitQuorumsCache() accordingly - for (const auto& params : Params().GetConsensus().llmqs) { if (quorumThreadInterrupt) { break; } - auto nQuorumsToKeep = params.type == Params().GetConsensus().llmqTypePlatform ? numPlatformQuorumsDataToKeep : params.keepOldConnections; - const auto vecQuorums = ScanQuorums(params.type, pIndex, nQuorumsToKeep); + const auto vecQuorums = ScanQuorums(params.type, pIndex, params.keepOldKeys); for (const auto& pQuorum : vecQuorums) { dbKeysToSkip.insert(MakeQuorumKey(*pQuorum)); } diff --git a/src/llmq/utils.cpp b/src/llmq/utils.cpp index e3685764dc61..dd0e2f209f1f 100644 --- a/src/llmq/utils.cpp +++ b/src/llmq/utils.cpp @@ -1087,13 +1087,9 @@ std::map GetEnabledQuorumVvecSyncEntries() template void InitQuorumsCache(CacheType& cache) { - // NOTE: See CQuorumManager::CleanupOldQuorumData() for more info - constexpr auto numPlatformQuorumsDataToKeep = 24 * 30 * 2; - const auto llmqTypePlatform = Params().GetConsensus().llmqTypePlatform; for (const auto& llmq : Params().GetConsensus().llmqs) { - const auto nQuorumsToKeep = llmq.type == llmqTypePlatform ? numPlatformQuorumsDataToKeep : llmq.keepOldConnections; cache.emplace(std::piecewise_construct, std::forward_as_tuple(llmq.type), - std::forward_as_tuple(nQuorumsToKeep)); + std::forward_as_tuple(llmq.keepOldKeys)); } } template void InitQuorumsCache>>(std::map>& cache); From e81de93ee23e2505fe64dc8945ab4720d7eaeb81 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Sun, 26 Nov 2023 22:00:54 +0300 Subject: [PATCH 07/10] fix: limit cache by keys for scanQuorumsCache and mapQuorumsCache only --- src/llmq/quorums.cpp | 4 ++-- src/llmq/utils.cpp | 12 ++++++------ src/llmq/utils.h | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 0b1e7f69223b..25798beecc71 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -200,8 +200,8 @@ CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CChainState& chainstate, m_mn_sync(mn_sync), m_peerman(peerman) { - utils::InitQuorumsCache(mapQuorumsCache); - utils::InitQuorumsCache(scanQuorumsCache); + utils::InitQuorumsCache(mapQuorumsCache, false); + utils::InitQuorumsCache(scanQuorumsCache, false); quorumThreadInterrupt.reset(); } diff --git a/src/llmq/utils.cpp b/src/llmq/utils.cpp index dd0e2f209f1f..56c4d161761b 100644 --- a/src/llmq/utils.cpp +++ b/src/llmq/utils.cpp @@ -1085,17 +1085,17 @@ std::map GetEnabledQuorumVvecSyncEntries() } template -void InitQuorumsCache(CacheType& cache) +void InitQuorumsCache(CacheType& cache, bool limit_by_connections) { for (const auto& llmq : Params().GetConsensus().llmqs) { cache.emplace(std::piecewise_construct, std::forward_as_tuple(llmq.type), - std::forward_as_tuple(llmq.keepOldKeys)); + std::forward_as_tuple(limit_by_connections ? llmq.keepOldConnections : llmq.keepOldKeys)); } } -template void InitQuorumsCache>>(std::map>& cache); -template void InitQuorumsCache, StaticSaltedHasher>>>(std::map, StaticSaltedHasher>>& cache); -template void InitQuorumsCache, StaticSaltedHasher, 0ul, 0ul>, std::less, std::allocator, StaticSaltedHasher, 0ul, 0ul>>>>>(std::map, StaticSaltedHasher, 0ul, 0ul>, std::less, std::allocator, StaticSaltedHasher, 0ul, 0ul>>>>&); -template void InitQuorumsCache>>(std::map>& cache); +template void InitQuorumsCache>>(std::map>& cache, bool limit_by_connections); +template void InitQuorumsCache, StaticSaltedHasher>>>(std::map, StaticSaltedHasher>>& cache, bool limit_by_connections); +template void InitQuorumsCache, StaticSaltedHasher, 0ul, 0ul>, std::less, std::allocator, StaticSaltedHasher, 0ul, 0ul>>>>>(std::map, StaticSaltedHasher, 0ul, 0ul>, std::less, std::allocator, StaticSaltedHasher, 0ul, 0ul>>>>&cache, bool limit_by_connections); +template void InitQuorumsCache>>(std::map>& cache, bool limit_by_connections); } // namespace utils diff --git a/src/llmq/utils.h b/src/llmq/utils.h index 3110603acb7d..f9e37dfed4b2 100644 --- a/src/llmq/utils.h +++ b/src/llmq/utils.h @@ -117,7 +117,7 @@ void IterateNodesRandom(NodesContainer& nodeStates, Continue&& cont, Callback&& } template -void InitQuorumsCache(CacheType& cache); +void InitQuorumsCache(CacheType& cache, bool limit_by_connections = true); } // namespace utils From be37a2f1cea33f894daf012ebdeebecff553886e Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Mon, 27 Nov 2023 19:07:46 +0300 Subject: [PATCH 08/10] fix: codestyle --- src/llmq/quorums.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 25798beecc71..5fe86f314b4e 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -1008,7 +1008,7 @@ void CQuorumManager::StartCleanupOldQuorumDataThread(const CBlockIndex* pIndex) return; } - cxxtimer::Timer t(true); + cxxtimer::Timer t(/*start=*/ true); LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- start\n", __func__); // do not block the caller thread From 67144b0784d4de1e2040c92400ca90a3ccb6b961 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Mon, 27 Nov 2023 21:14:21 +0300 Subject: [PATCH 09/10] fix: consolidate Co-authored-by: PastaPastaPasta <6443210+PastaPastaPasta@users.noreply.github.com> --- src/llmq/quorums.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 5fe86f314b4e..0fde2f582e0c 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -1019,8 +1019,7 @@ void CQuorumManager::StartCleanupOldQuorumDataThread(const CBlockIndex* pIndex) if (quorumThreadInterrupt) { break; } - const auto vecQuorums = ScanQuorums(params.type, pIndex, params.keepOldKeys); - for (const auto& pQuorum : vecQuorums) { + for (const auto& pQuorum : ScanQuorums(params.type, pIndex, params.keepOldKeys)) { dbKeysToSkip.insert(MakeQuorumKey(*pQuorum)); } } From 5684fb715dd57c85885f32ba4a49c5dc9151dc33 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Mon, 27 Nov 2023 21:41:24 +0300 Subject: [PATCH 10/10] fix: add comment why 58 --- src/llmq/quorums.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 0fde2f582e0c..5b4fac4fb2a3 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -1004,7 +1004,14 @@ static void DataCleanupHelper(CDBWrapper& db, std::set skip_list, bool void CQuorumManager::StartCleanupOldQuorumDataThread(const CBlockIndex* pIndex) const { - if (!fMasternodeMode || pIndex == nullptr || (pIndex->nHeight % 576 != 58 /* no DKGs running or to be started soon */)) { + // Note: this function is CPU heavy and we don't want it to be running during DKGs. + // The largest dkgMiningWindowStart for a related quorum type is 42 (LLMQ_60_75). + // At the same time most quorums use dkgInterval = 24 so the next DKG for them + // (after block 576 + 42) will start at block 576 + 24 * 2. That's only a 6 blocks + // window and it's better to have more room so we pick next cycle. + // dkgMiningWindowStart for small quorums is 10 i.e. a safe block to start + // these calculations is at height 576 + 24 * 2 + 10 = 576 + 58. + if (!fMasternodeMode || pIndex == nullptr || (pIndex->nHeight % 576 != 58)) { return; }