@@ -39,6 +39,8 @@ static const std::string DB_ARCHIVED_BY_HASH = "is_a2";
3939static const std::string DB_VERSION = " is_v" ;
4040
4141const int CInstantSendDb::CURRENT_VERSION;
42+ const uint8_t CInstantSendLock::islock_version;
43+ const uint8_t CInstantSendLock::isdlock_version;
4244
4345CInstantSendManager* quorumInstantSendManager;
4446
@@ -325,10 +327,14 @@ CInstantSendLockPtr CInstantSendDb::GetInstantSendLockByHash(const uint256& hash
325327 return ret;
326328 }
327329
328- ret = std::make_shared<CInstantSendLock>();
330+ ret = std::make_shared<CInstantSendLock>(CInstantSendLock::isdlock_version );
329331 bool exists = db->Read (std::make_tuple (DB_ISLOCK_BY_HASH, hash), *ret);
330332 if (!exists) {
331- ret = nullptr ;
333+ ret = std::make_shared<CInstantSendLock>();
334+ exists = db->Read (std::make_tuple (DB_ISLOCK_BY_HASH, hash), *ret);
335+ if (!exists) {
336+ ret = nullptr ;
337+ }
332338 }
333339 islockCache.insert (hash, ret);
334340 return ret;
@@ -686,7 +692,7 @@ void CInstantSendManager::HandleNewInputLockRecoveredSig(const CRecoveredSig& re
686692
687693void CInstantSendManager::TrySignInstantSendLock (const CTransaction& tx)
688694{
689- auto llmqType = Params ().GetConsensus ().llmqTypeInstantSend ;
695+ const auto llmqType = Params ().GetConsensus ().llmqTypeInstantSend ;
690696
691697 for (auto & in : tx.vin ) {
692698 auto id = ::SerializeHash (std::make_pair (INPUTLOCK_REQUESTID_PREFIX, in.prevout ));
@@ -698,12 +704,20 @@ void CInstantSendManager::TrySignInstantSendLock(const CTransaction& tx)
698704 LogPrint (BCLog::INSTANTSEND, " CInstantSendManager::%s -- txid=%s: got all recovered sigs, creating CInstantSendLock\n " , __func__,
699705 tx.GetHash ().ToString ());
700706
701- CInstantSendLock islock;
707+ CInstantSendLock islock (CInstantSendLock::isdlock_version) ;
702708 islock.txid = tx.GetHash ();
703709 for (auto & in : tx.vin ) {
704710 islock.inputs .emplace_back (in.prevout );
705711 }
706712
713+ // compute cycle hash
714+ {
715+ LOCK (cs_main);
716+ const auto dkgInterval = GetLLMQParams (llmqType).dkgInterval ;
717+ const auto quorumHeight = chainActive.Height () - (chainActive.Height () % dkgInterval);
718+ islock.cycleHash = chainActive[quorumHeight]->GetBlockHash ();
719+ }
720+
707721 auto id = islock.GetRequestId ();
708722
709723 if (quorumSigningManager->HasRecoveredSigForId (llmqType, id)) {
@@ -760,8 +774,9 @@ void CInstantSendManager::ProcessMessage(CNode* pfrom, const std::string& strCom
760774 return ;
761775 }
762776
763- if (strCommand == NetMsgType::ISLOCK) {
764- auto islock = std::make_shared<CInstantSendLock>();
777+ if (strCommand == NetMsgType::ISLOCK || strCommand == NetMsgType::ISDLOCK) {
778+ const auto islock_version = strCommand == NetMsgType::ISLOCK ? CInstantSendLock::islock_version : CInstantSendLock::isdlock_version;
779+ const auto islock = std::make_shared<CInstantSendLock>(islock_version);
765780 vRecv >> *islock;
766781 ProcessMessageInstantSendLock (pfrom, islock);
767782 }
@@ -775,14 +790,29 @@ void CInstantSendManager::ProcessMessageInstantSendLock(const CNode* pfrom, cons
775790
776791 {
777792 LOCK (cs_main);
778- EraseObjectRequest (pfrom->GetId (), CInv (MSG_ISLOCK, hash));
793+ EraseObjectRequest (pfrom->GetId (), CInv (islock-> IsDeterministic () ? MSG_ISDLOCK : MSG_ISLOCK, hash));
779794 }
780795
781796 if (!PreVerifyInstantSendLock (*islock)) {
782797 LOCK (cs_main);
783798 Misbehaving (pfrom->GetId (), 100 );
784799 return ;
785800 }
801+ if (islock->IsDeterministic ()) {
802+ const auto blockIndex = WITH_LOCK (cs_main, return LookupBlockIndex (islock->cycleHash ));
803+ if (blockIndex == nullptr ) {
804+ // Maybe we don't have the block yet or maybe some peer spams invalid values for cycleHash
805+ WITH_LOCK (cs_main, Misbehaving (pfrom->GetId (), 1 ));
806+ return ;
807+ }
808+
809+ const auto llmqType = Params ().GetConsensus ().llmqTypeInstantSend ;
810+ const auto dkgInterval = GetLLMQParams (llmqType).dkgInterval ;
811+ if (blockIndex->nHeight % dkgInterval != 0 ) {
812+ WITH_LOCK (cs_main, Misbehaving (pfrom->GetId (), 100 ));
813+ return ;
814+ }
815+ }
786816
787817 LOCK (cs);
788818 if (pendingInstantSendLocks.count (hash) || db.KnownInstantSendLock (hash)) {
@@ -901,7 +931,23 @@ std::unordered_set<uint256> CInstantSendManager::ProcessPendingInstantSendLocks(
901931 continue ;
902932 }
903933
904- auto quorum = llmq::CSigningManager::SelectQuorumForSigning (llmqType, id, -1 , signOffset);
934+ int nSignHeight{-1 };
935+ if (islock->IsDeterministic ()) {
936+ LOCK (cs_main);
937+
938+ const auto blockIndex = LookupBlockIndex (islock->cycleHash );
939+ if (blockIndex == nullptr ) {
940+ batchVerifier.badSources .emplace (nodeId);
941+ continue ;
942+ }
943+
944+ const auto dkgInterval = GetLLMQParams (Params ().GetConsensus ().llmqTypeInstantSend ).dkgInterval ;
945+ if (blockIndex->nHeight + dkgInterval < chainActive.Height ()) {
946+ nSignHeight = blockIndex->nHeight + dkgInterval - 1 ;
947+ }
948+ }
949+
950+ auto quorum = llmq::CSigningManager::SelectQuorumForSigning (llmqType, id, nSignHeight, signOffset);
905951 if (!quorum) {
906952 // should not happen, but if one fails to select, all others will also fail to select
907953 return {};
@@ -1028,13 +1074,14 @@ void CInstantSendManager::ProcessInstantSendLock(NodeId from, const uint256& has
10281074 TruncateRecoveredSigsForInputs (*islock);
10291075 }
10301076
1031- CInv inv (MSG_ISLOCK, hash);
1077+ const auto is_det = islock->IsDeterministic ();
1078+ CInv inv (is_det ? MSG_ISDLOCK : MSG_ISLOCK, hash);
10321079 if (tx != nullptr ) {
1033- g_connman->RelayInvFiltered (inv, *tx, LLMQS_PROTO_VERSION);
1080+ g_connman->RelayInvFiltered (inv, *tx, is_det ? ISDLOCK_PROTO_VERSION : LLMQS_PROTO_VERSION);
10341081 } else {
10351082 // we don't have the TX yet, so we only filter based on txid. Later when that TX arrives, we will re-announce
10361083 // with the TX taken into account.
1037- g_connman->RelayInvFiltered (inv, islock->txid , LLMQS_PROTO_VERSION);
1084+ g_connman->RelayInvFiltered (inv, islock->txid , is_det ? ISDLOCK_PROTO_VERSION : LLMQS_PROTO_VERSION);
10381085 }
10391086
10401087 ResolveBlockConflicts (hash, *islock);
@@ -1068,8 +1115,8 @@ void CInstantSendManager::TransactionAddedToMempool(const CTransactionRef& tx)
10681115 }
10691116 // In case the islock was received before the TX, filtered announcement might have missed this islock because
10701117 // we were unable to check for filter matches deep inside the TX. Now we have the TX, so we should retry.
1071- CInv inv (MSG_ISLOCK, ::SerializeHash (*islock));
1072- g_connman->RelayInvFiltered (inv, *tx, LLMQS_PROTO_VERSION);
1118+ CInv inv (islock-> IsDeterministic () ? MSG_ISDLOCK : MSG_ISLOCK, ::SerializeHash (*islock));
1119+ g_connman->RelayInvFiltered (inv, *tx, islock-> IsDeterministic () ? ISDLOCK_PROTO_VERSION : LLMQS_PROTO_VERSION);
10731120 // If the islock was received before the TX, we know we were not able to send
10741121 // the notification at that time, we need to do it now.
10751122 LogPrint (BCLog::INSTANTSEND, " CInstantSendManager::%s -- notify about an earlier received lock for tx %s\n " , __func__, tx->GetHash ().ToString ());
0 commit comments