From c20dfd8534a4791b8cee6c7247955b7a91c6e4c2 Mon Sep 17 00:00:00 2001
From: UdjinM6 <UdjinM6@users.noreply.github.com>
Date: Tue, 4 Mar 2025 18:10:49 +0300
Subject: [PATCH 1/3] fix: `cycleHash` should represent a cycle starting block
 of the signing quorum

---
 src/llmq/instantsend.cpp | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/src/llmq/instantsend.cpp b/src/llmq/instantsend.cpp
index 19869910f626..65c881826b99 100644
--- a/src/llmq/instantsend.cpp
+++ b/src/llmq/instantsend.cpp
@@ -672,21 +672,26 @@ void CInstantSendManager::TrySignInstantSendLock(const CTransaction& tx)
         islock.inputs.emplace_back(in.prevout);
     }
 
-    {
-        const auto &llmq_params_opt = Params().GetLLMQ(llmqType);
-        assert(llmq_params_opt);
-        LOCK(cs_main);
-        const auto dkgInterval = llmq_params_opt->dkgInterval;
-        const auto quorumHeight = m_chainstate.m_chain.Height() - (m_chainstate.m_chain.Height() % dkgInterval);
-        islock.cycleHash = m_chainstate.m_chain[quorumHeight]->GetBlockHash();
-    }
-
     auto id = islock.GetRequestId();
 
     if (sigman.HasRecoveredSigForId(llmqType, id)) {
         return;
     }
 
+    const auto& llmq_params_opt = Params().GetLLMQ(llmqType);
+    assert(llmq_params_opt);
+    const auto quorum = SelectQuorumForSigning(llmq_params_opt.value(), m_chainstate.m_chain, qman, id);
+
+    if (!quorum) {
+        LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- failed to select quorum. islock id=%s, txid=%s\n",
+                 __func__, id.ToString(), tx.GetHash().ToString());
+        return;
+    }
+
+    const int cycle_height = quorum->m_quorum_base_block_index->nHeight -
+                             quorum->m_quorum_base_block_index->nHeight % llmq_params_opt->dkgInterval;
+    islock.cycleHash = quorum->m_quorum_base_block_index->GetAncestor(cycle_height)->GetBlockHash();
+
     {
         LOCK(cs_creating);
         auto e = creatingInstantSendLocks.emplace(id, std::move(islock));
@@ -696,7 +701,7 @@ void CInstantSendManager::TrySignInstantSendLock(const CTransaction& tx)
         txToCreatingInstantSendLocks.emplace(tx.GetHash(), &e.first->second);
     }
 
-    sigman.AsyncSignIfMember(llmqType, shareman, id, tx.GetHash());
+    sigman.AsyncSignIfMember(llmqType, shareman, id, tx.GetHash(), quorum->m_quorum_base_block_index->GetBlockHash());
 }
 
 void CInstantSendManager::HandleNewInstantSendLockRecoveredSig(const llmq::CRecoveredSig& recoveredSig)

From 85c6b58d1e2a81be4ddf2f9a64c0a837d788a833 Mon Sep 17 00:00:00 2001
From: UdjinM6 <UdjinM6@users.noreply.github.com>
Date: Tue, 4 Mar 2025 19:26:56 +0300
Subject: [PATCH 2/3] feat: bump PROTOCOL_VERSION/MIN_MASTERNODE_PROTO_VERSION
 to 70237

---
 src/version.h                         | 7 +++++--
 test/functional/test_framework/p2p.py | 4 ++--
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/version.h b/src/version.h
index c412cacec0c4..025c3ea7beb6 100644
--- a/src/version.h
+++ b/src/version.h
@@ -11,7 +11,7 @@
  */
 
 
-static const int PROTOCOL_VERSION = 70236;
+static const int PROTOCOL_VERSION = 70237;
 
 //! initial proto version, to be increased after version/verack negotiation
 static const int INIT_PROTO_VERSION = 209;
@@ -20,7 +20,7 @@ static const int INIT_PROTO_VERSION = 209;
 static const int MIN_PEER_PROTO_VERSION = 70216;
 
 //! minimum proto version of masternode to accept in DKGs
-static const int MIN_MASTERNODE_PROTO_VERSION = 70235;
+static const int MIN_MASTERNODE_PROTO_VERSION = 70237;
 
 //! protocol version is included in MNAUTH starting with this version
 static const int MNAUTH_NODE_VER_VERSION = 70218;
@@ -64,6 +64,9 @@ static const int INCREASE_MAX_HEADERS2_VERSION = 70235;
 //! Behavior of QRINFO is changed in this protocol version
 static const int EFFICIENT_QRINFO_VERSION = 70236;
 
+//! cycleHash in isdlock message switched to using quorum's base block in this version
+static const int ISDLOCK_CYCLEHASH_UPDATE_VERSION = 70237;
+
 // Make sure that none of the values above collide with `ADDRV2_FORMAT`.
 
 #endif // BITCOIN_VERSION_H
diff --git a/test/functional/test_framework/p2p.py b/test/functional/test_framework/p2p.py
index a7844d231465..1eed6df9a933 100755
--- a/test/functional/test_framework/p2p.py
+++ b/test/functional/test_framework/p2p.py
@@ -99,8 +99,8 @@
 # The minimum P2P version that this test framework supports
 MIN_P2P_VERSION_SUPPORTED = 60001
 # The P2P version that this test framework implements and sends in its `version` message
-# Version 70235 increased max header count for HEADERS2 message from 2000 to 8000
-P2P_VERSION = 70236
+# Version 70237 switched cycleHash in isdlock message to using quorum's base block
+P2P_VERSION = 70237
 # The services that this test framework offers in its `version` message
 P2P_SERVICES = NODE_NETWORK | NODE_HEADERS_COMPRESSED
 # The P2P user agent string that this test framework sends in its `version` message

From d150a65c5b8a73453fda4cf76a26d75ff0cc27ee Mon Sep 17 00:00:00 2001
From: UdjinM6 <UdjinM6@users.noreply.github.com>
Date: Wed, 9 Apr 2025 12:17:44 +0300
Subject: [PATCH 3/3] docs: add release notes

---
 doc/release-notes-6608.md | 4 ++++
 1 file changed, 4 insertions(+)
 create mode 100644 doc/release-notes-6608.md

diff --git a/doc/release-notes-6608.md b/doc/release-notes-6608.md
new file mode 100644
index 000000000000..ecf8f4d7f438
--- /dev/null
+++ b/doc/release-notes-6608.md
@@ -0,0 +1,4 @@
+P2P Changes
+-----------
+
+* `cycleHash` field in `isdlock` message will now represent a DKG cycle starting block of the signing quorum instead of a DKG cycle starting block corresponding to the current chain height. While this is fully backwards compatible with older versions of Dash Core, other implementations might not be expecting this, so the P2P protocol version was bumped to 70237.
