LCOV - code coverage report
Current view: top level - src/governance - vote.cpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 0 139 0.0 %
Date: 2026-06-25 07:23:51 Functions: 0 14 0.0 %

          Line data    Source code
       1             : // Copyright (c) 2014-2025 The Dash Core developers
       2             : // Distributed under the MIT/X11 software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include <governance/vote.h>
       6             : 
       7             : #include <bls/bls.h>
       8             : #include <evo/deterministicmns.h>
       9             : #include <evo/dmn_types.h>
      10             : #include <masternode/sync.h>
      11             : #include <messagesigner.h>
      12             : 
      13             : #include <chainparams.h>
      14             : #include <logging.h>
      15             : #include <timedata.h>
      16             : #include <util/string.h>
      17             : 
      18           0 : std::string CGovernanceVoting::ConvertOutcomeToString(vote_outcome_enum_t nOutcome)
      19             : {
      20           0 :     static const std::map<vote_outcome_enum_t, std::string> mapOutcomeString = {
      21           0 :         { VOTE_OUTCOME_NONE, "none" },
      22           0 :         { VOTE_OUTCOME_YES, "yes" },
      23           0 :         { VOTE_OUTCOME_NO, "no" },
      24           0 :         { VOTE_OUTCOME_ABSTAIN, "abstain" } };
      25             : 
      26           0 :     const auto& it = mapOutcomeString.find(nOutcome);
      27           0 :     if (it == mapOutcomeString.end()) {
      28           0 :         LogPrintf("CGovernanceVoting::%s -- ERROR: Unknown outcome %d\n", __func__, nOutcome);
      29           0 :         return "error";
      30             :     }
      31           0 :     return it->second;
      32           0 : }
      33             : 
      34           0 : std::string CGovernanceVoting::ConvertSignalToString(vote_signal_enum_t nSignal)
      35             : {
      36           0 :     static const std::map<vote_signal_enum_t, std::string> mapSignalsString = {
      37           0 :         { VOTE_SIGNAL_FUNDING, "funding" },
      38           0 :         { VOTE_SIGNAL_VALID, "valid" },
      39           0 :         { VOTE_SIGNAL_DELETE, "delete" },
      40           0 :         { VOTE_SIGNAL_ENDORSED, "endorsed" } };
      41             : 
      42           0 :     const auto& it = mapSignalsString.find(nSignal);
      43           0 :     if (it == mapSignalsString.end()) {
      44           0 :         LogPrintf("CGovernanceVoting::%s -- ERROR: Unknown signal %d\n", __func__, nSignal);
      45           0 :         return "none";
      46             :     }
      47           0 :     return it->second;
      48           0 : }
      49             : 
      50             : 
      51           0 : vote_outcome_enum_t CGovernanceVoting::ConvertVoteOutcome(const std::string& strVoteOutcome)
      52             : {
      53           0 :     static const std::map<std::string, vote_outcome_enum_t> mapStringOutcome = {
      54           0 :         { "none", VOTE_OUTCOME_NONE },
      55           0 :         { "yes", VOTE_OUTCOME_YES },
      56           0 :         { "no", VOTE_OUTCOME_NO },
      57           0 :         { "abstain", VOTE_OUTCOME_ABSTAIN } };
      58             : 
      59           0 :     const auto& it = mapStringOutcome.find(strVoteOutcome);
      60           0 :     if (it == mapStringOutcome.end()) {
      61           0 :         LogPrintf("CGovernanceVoting::%s -- ERROR: Unknown outcome %s\n", __func__, strVoteOutcome);
      62           0 :         return VOTE_OUTCOME_NONE;
      63             :     }
      64           0 :     return it->second;
      65             : 
      66           0 : }
      67             : 
      68           0 : vote_signal_enum_t CGovernanceVoting::ConvertVoteSignal(const std::string& strVoteSignal)
      69             : {
      70           0 :     static const std::map<std::string, vote_signal_enum_t> mapStrVoteSignals = {
      71           0 :         {"funding", VOTE_SIGNAL_FUNDING},
      72           0 :         {"valid", VOTE_SIGNAL_VALID},
      73           0 :         {"delete", VOTE_SIGNAL_DELETE},
      74           0 :         {"endorsed", VOTE_SIGNAL_ENDORSED}};
      75             : 
      76           0 :     const auto& it = mapStrVoteSignals.find(strVoteSignal);
      77           0 :     if (it == mapStrVoteSignals.end()) {
      78           0 :         LogPrintf("CGovernanceVoting::%s -- ERROR: Unknown signal %s\n", __func__, strVoteSignal);
      79           0 :         return VOTE_SIGNAL_NONE;
      80             :     }
      81           0 :     return it->second;
      82           0 : }
      83             : 
      84           0 : CGovernanceVote::CGovernanceVote(const COutPoint& outpointMasternodeIn, const uint256& nParentHashIn,
      85             :                                  vote_signal_enum_t eVoteSignalIn, vote_outcome_enum_t eVoteOutcomeIn) :
      86           0 :     masternodeOutpoint(outpointMasternodeIn),
      87           0 :     nParentHash(nParentHashIn),
      88           0 :     nVoteOutcome(eVoteOutcomeIn),
      89           0 :     nVoteSignal(eVoteSignalIn),
      90           0 :     nTime(GetAdjustedTime())
      91           0 : {
      92             :     UpdateHash();
      93           0 : }
      94             : 
      95           0 : std::string CGovernanceVote::ToString(const CDeterministicMNList& tip_mn_list) const
      96             : {
      97           0 :     auto dmn = tip_mn_list.GetMNByCollateral(masternodeOutpoint);
      98           0 :     int voteWeight = dmn != nullptr ? GetMnType(dmn->nType).voting_weight : 0;
      99           0 :     return strprintf("%s:%d:%s:%s:%d",
     100           0 :         masternodeOutpoint.ToStringShort(), nTime,
     101           0 :         CGovernanceVoting::ConvertOutcomeToString(GetOutcome()), CGovernanceVoting::ConvertSignalToString(GetSignal()),
     102             :         voteWeight);
     103           0 : }
     104             : 
     105           0 : void CGovernanceVote::UpdateHash() const
     106             : {
     107             :     // Note: doesn't match serialization
     108             : 
     109           0 :     CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
     110           0 :     ss << masternodeOutpoint << uint8_t{} << 0xffffffff; // adding dummy values here to match old hashing format
     111           0 :     ss << nParentHash;
     112           0 :     ss << nVoteSignal;
     113           0 :     ss << nVoteOutcome;
     114           0 :     ss << nTime;
     115           0 :     *const_cast<uint256*>(&hash) = ss.GetHash();
     116           0 : }
     117             : 
     118           0 : uint256 CGovernanceVote::GetHash() const
     119             : {
     120           0 :     return hash;
     121             : }
     122             : 
     123             : 
     124           0 : bool CGovernanceVote::CheckSignature(const CKeyID& keyID) const
     125             : {
     126           0 :     std::string strError;
     127             : 
     128             :     // Harden Spork6 so that it is active on testnet and no other networks
     129           0 :     if (Params().NetworkIDString() == CBaseChainParams::TESTNET) {
     130           0 :         if (!CHashSigner::VerifyHash(GetSignatureHash(), keyID, vchSig, strError)) {
     131           0 :             LogPrint(BCLog::GOBJECT, "CGovernanceVote::IsValid -- VerifyHash() failed, error: %s\n", strError);
     132           0 :             return false;
     133             :         }
     134           0 :     } else {
     135           0 :         if (!CMessageSigner::VerifyMessage(keyID, vchSig, GetSignatureString(), strError)) {
     136           0 :             LogPrint(BCLog::GOBJECT, "CGovernanceVote::IsValid -- VerifyMessage() failed, error: %s\n", strError);
     137           0 :             return false;
     138             :         }
     139             :     }
     140             : 
     141           0 :     return true;
     142           0 : }
     143             : 
     144           0 : bool CGovernanceVote::CheckSignature(const CBLSPublicKey& pubKey) const
     145             : {
     146           0 :     CBLSSignature sig;
     147           0 :     sig.SetBytes(vchSig, false);
     148           0 :     if (!sig.VerifyInsecure(pubKey, GetSignatureHash(), false)) {
     149           0 :         LogPrintf("CGovernanceVote::CheckSignature -- VerifyInsecure() failed\n");
     150           0 :         return false;
     151             :     }
     152           0 :     return true;
     153           0 : }
     154             : 
     155           0 : bool CGovernanceVote::IsValid(const CDeterministicMNList& tip_mn_list, bool useVotingKey) const
     156             : {
     157           0 :     if (nTime > GetAdjustedTime() + (60 * 60)) {
     158           0 :         LogPrint(BCLog::GOBJECT, "CGovernanceVote::IsValid -- vote is too far ahead of current time - %s - nTime %lli - Max Time %lli\n", GetHash().ToString(), nTime, GetAdjustedTime() + (60 * 60));
     159           0 :         return false;
     160             :     }
     161             : 
     162           0 :     if (nVoteSignal < VOTE_SIGNAL_NONE || nVoteSignal >= VOTE_SIGNAL_UNKNOWN) {
     163           0 :         LogPrint(BCLog::GOBJECT, "CGovernanceVote::IsValid -- Client attempted to vote on invalid signal(%d) - %s\n",
     164             :                  nVoteSignal, GetHash().ToString());
     165           0 :         return false;
     166             :     }
     167             : 
     168           0 :     if (nVoteOutcome < VOTE_OUTCOME_NONE || nVoteOutcome >= VOTE_OUTCOME_UNKNOWN) {
     169           0 :         LogPrint(BCLog::GOBJECT, "CGovernanceVote::IsValid -- Client attempted to vote on invalid outcome(%d) - %s\n",
     170             :                  nVoteOutcome, GetHash().ToString());
     171           0 :         return false;
     172             :     }
     173             : 
     174           0 :     auto dmn = tip_mn_list.GetMNByCollateral(masternodeOutpoint);
     175           0 :     if (!dmn) {
     176           0 :         LogPrint(BCLog::GOBJECT, "CGovernanceVote::IsValid -- Unknown Masternode - %s\n", masternodeOutpoint.ToStringShort());
     177           0 :         return false;
     178             :     }
     179             : 
     180           0 :     if (useVotingKey) {
     181           0 :         return CheckSignature(dmn->pdmnState->keyIDVoting);
     182             :     } else {
     183           0 :         return CheckSignature(dmn->pdmnState->pubKeyOperator.Get());
     184             :     }
     185           0 : }
     186             : 
     187             : 
     188           0 : bool operator==(const CGovernanceVote& vote1, const CGovernanceVote& vote2)
     189             : {
     190           0 :     bool fResult = ((vote1.masternodeOutpoint == vote2.masternodeOutpoint) &&
     191           0 :                     (vote1.nParentHash == vote2.nParentHash) &&
     192           0 :                     (vote1.nVoteOutcome == vote2.nVoteOutcome) &&
     193           0 :                     (vote1.nVoteSignal == vote2.nVoteSignal) &&
     194           0 :                     (vote1.nTime == vote2.nTime));
     195           0 :     return fResult;
     196             : }
     197             : 
     198           0 : bool operator<(const CGovernanceVote& vote1, const CGovernanceVote& vote2)
     199             : {
     200           0 :     bool fResult = (vote1.masternodeOutpoint < vote2.masternodeOutpoint);
     201           0 :     if (!fResult) {
     202           0 :         return false;
     203             :     }
     204           0 :     fResult = (vote1.masternodeOutpoint == vote2.masternodeOutpoint);
     205             : 
     206           0 :     fResult = fResult && (vote1.nParentHash < vote2.nParentHash);
     207           0 :     if (!fResult) {
     208           0 :         return false;
     209             :     }
     210           0 :     fResult = (vote1.nParentHash == vote2.nParentHash);
     211             : 
     212           0 :     fResult = fResult && (vote1.nVoteOutcome < vote2.nVoteOutcome);
     213           0 :     if (!fResult) {
     214           0 :         return false;
     215             :     }
     216           0 :     fResult = (vote1.nVoteOutcome == vote2.nVoteOutcome);
     217             : 
     218           0 :     fResult = fResult && (vote1.nVoteSignal == vote2.nVoteSignal);
     219           0 :     if (!fResult) {
     220           0 :         return false;
     221             :     }
     222           0 :     fResult = (vote1.nVoteSignal == vote2.nVoteSignal);
     223             : 
     224           0 :     fResult = fResult && (vote1.nTime < vote2.nTime);
     225             : 
     226           0 :     return fResult;
     227           0 : }

Generated by: LCOV version 1.16