diff --git a/src/instantx.cpp b/src/instantx.cpp index a8fe3f982..49cf7aea7 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -244,11 +244,16 @@ void CInstantSend::Vote(CTxLockCandidate& txLockCandidate, CConnman& connman) int nLockInputHeight = nPrevoutHeight + Params().GetConsensus().nInstantSendConfirmationsRequired - 2; int nRank; + uint256 quorumModifierHash; int nMinRequiredProtocol = std::max(MIN_INSTANTSEND_PROTO_VERSION, mnpayments.GetMinMasternodePaymentsProto()); - if (!mnodeman.GetMasternodeRank(activeMasternodeInfo.outpoint, nRank, nLockInputHeight, nMinRequiredProtocol)) { + if (!mnodeman.GetMasternodeRank(activeMasternodeInfo.outpoint, nRank, quorumModifierHash, nLockInputHeight, nMinRequiredProtocol)) { LogPrint("instantsend", "CInstantSend::Vote -- Can't calculate rank for masternode %s\n", activeMasternodeInfo.outpoint.ToStringShort()); continue; } + if (!deterministicMNManager->IsDeterministicMNsSporkActive()) { + // not used until spork15 activation + quorumModifierHash = uint256(); + } int nSignaturesTotal = COutPointLock::SIGNATURES_TOTAL; if (nRank > nSignaturesTotal) { @@ -282,7 +287,7 @@ void CInstantSend::Vote(CTxLockCandidate& txLockCandidate, CConnman& connman) // we haven't voted for this outpoint yet, let's try to do this now // Please note that activeMasternodeInfo.proTxHash is only valid after spork15 activation - CTxLockVote vote(txHash, outpointLockPair.first, activeMasternodeInfo.outpoint, activeMasternodeInfo.proTxHash); + CTxLockVote vote(txHash, outpointLockPair.first, activeMasternodeInfo.outpoint, quorumModifierHash, activeMasternodeInfo.proTxHash); if (!vote.Sign()) { LogPrintf("CInstantSend::Vote -- Failed to sign consensus vote\n"); @@ -1052,12 +1057,23 @@ bool CTxLockVote::IsValid(CNode* pnode, CConnman& connman) const int nLockInputHeight = coin.nHeight + Params().GetConsensus().nInstantSendConfirmationsRequired - 2; int nRank; + uint256 expectedQuorumModifierHash; int nMinRequiredProtocol = std::max(MIN_INSTANTSEND_PROTO_VERSION, mnpayments.GetMinMasternodePaymentsProto()); - if (!mnodeman.GetMasternodeRank(outpointMasternode, nRank, nLockInputHeight, nMinRequiredProtocol)) { + if (!mnodeman.GetMasternodeRank(outpointMasternode, nRank, expectedQuorumModifierHash, nLockInputHeight, nMinRequiredProtocol)) { //can be caused by past versions trying to vote with an invalid protocol LogPrint("instantsend", "CTxLockVote::IsValid -- Can't calculate rank for masternode %s\n", outpointMasternode.ToStringShort()); return false; } + if (!quorumModifierHash.IsNull()) { + if (quorumModifierHash != expectedQuorumModifierHash) { + LogPrint("instantsend", "CTxLockVote::IsValid -- invalid quorumModifierHash %s, expected %s\n", quorumModifierHash.ToString(), expectedQuorumModifierHash.ToString()); + return false; + } + } else if (deterministicMNManager->IsDeterministicMNsSporkActive()) { + LogPrint("instantsend", "CTxLockVote::IsValid -- missing quorumModifierHash while DIP3 is active\n"); + return false; + } + LogPrint("instantsend", "CTxLockVote::IsValid -- Masternode %s, rank=%d\n", outpointMasternode.ToStringShort(), nRank); int nSignaturesTotal = COutPointLock::SIGNATURES_TOTAL; diff --git a/src/instantx.h b/src/instantx.h index db0f0f12c..31bf593ed 100644 --- a/src/instantx.h +++ b/src/instantx.h @@ -235,6 +235,7 @@ private: COutPoint outpoint; // TODO remove this member when the legacy masternode code is removed after DIP3 deployment COutPoint outpointMasternode; + uint256 quorumModifierHash; uint256 masternodeProTxHash; std::vector vchMasternodeSignature; // local memory only @@ -246,16 +247,18 @@ public: txHash(), outpoint(), outpointMasternode(), + quorumModifierHash(), masternodeProTxHash(), vchMasternodeSignature(), nConfirmedHeight(-1), nTimeCreated(GetTime()) {} - CTxLockVote(const uint256& txHashIn, const COutPoint& outpointIn, const COutPoint& outpointMasternodeIn, const uint256& masternodeProTxHashIn) : + CTxLockVote(const uint256& txHashIn, const COutPoint& outpointIn, const COutPoint& outpointMasternodeIn, const uint256& quorumModifierHashIn, const uint256& masternodeProTxHashIn) : txHash(txHashIn), outpoint(outpointIn), outpointMasternode(outpointMasternodeIn), + quorumModifierHash(quorumModifierHashIn), masternodeProTxHash(masternodeProTxHashIn), vchMasternodeSignature(), nConfirmedHeight(-1), @@ -270,8 +273,9 @@ public: READWRITE(outpoint); READWRITE(outpointMasternode); if (deterministicMNManager->IsDeterministicMNsSporkActive()) { - // Starting with spork15 activation, the proTxHash is included. When we bump to >= 70213, we can remove + // Starting with spork15 activation, the proTxHash and quorumModifierHash is included. When we bump to >= 70213, we can remove // the surrounding if. We might also remove outpointMasternode as well later + READWRITE(quorumModifierHash); READWRITE(masternodeProTxHash); } if (!(s.GetType() & SER_GETHASH)) { diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index dc9698c86..4f8910fa1 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -821,6 +821,12 @@ bool CMasternodeMan::GetMasternodeScores(const uint256& nBlockHash, CMasternodeM } bool CMasternodeMan::GetMasternodeRank(const COutPoint& outpoint, int& nRankRet, int nBlockHeight, int nMinProtocol) +{ + uint256 tmp; + return GetMasternodeRank(outpoint, nRankRet, tmp, nBlockHeight, nMinProtocol); +} + +bool CMasternodeMan::GetMasternodeRank(const COutPoint& outpoint, int& nRankRet, uint256& blockHashRet, int nBlockHeight, int nMinProtocol) { nRankRet = -1; @@ -828,8 +834,8 @@ bool CMasternodeMan::GetMasternodeRank(const COutPoint& outpoint, int& nRankRet, return false; // make sure we know about this block - uint256 nBlockHash = uint256(); - if (!GetBlockHash(nBlockHash, nBlockHeight)) { + blockHashRet = uint256(); + if (!GetBlockHash(blockHashRet, nBlockHeight)) { LogPrintf("CMasternodeMan::%s -- ERROR: GetBlockHash() failed at nBlockHeight %d\n", __func__, nBlockHeight); return false; } @@ -837,7 +843,7 @@ bool CMasternodeMan::GetMasternodeRank(const COutPoint& outpoint, int& nRankRet, LOCK(cs); score_pair_vec_t vecMasternodeScores; - if (!GetMasternodeScores(nBlockHash, vecMasternodeScores, nMinProtocol)) + if (!GetMasternodeScores(blockHashRet, vecMasternodeScores, nMinProtocol)) return false; int nRank = 0; diff --git a/src/masternodeman.h b/src/masternodeman.h index 3e14b23b9..853fed868 100644 --- a/src/masternodeman.h +++ b/src/masternodeman.h @@ -187,6 +187,7 @@ public: bool GetMasternodeRanks(rank_pair_vec_t& vecMasternodeRanksRet, int nBlockHeight = -1, int nMinProtocol = 0); bool GetMasternodeRank(const COutPoint &outpoint, int& nRankRet, int nBlockHeight = -1, int nMinProtocol = 0); + bool GetMasternodeRank(const COutPoint &outpoint, int& nRankRet, uint256& blockHashRet, int nBlockHeight = -1, int nMinProtocol = 0); void ProcessMasternodeConnections(CConnman& connman); std::pair > PopScheduledMnbRequestConnection();