Line data Source code
1 : // Copyright (c) 2014-2024 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/votedb.h> 6 : 7 : #include <streams.h> 8 : 9 1814 : CGovernanceObjectVoteFile::CGovernanceObjectVoteFile() : 10 : listVotes(), 11 : mapVoteIndex() 12 907 : { 13 907 : } 14 : 15 125040 : CGovernanceObjectVoteFile::CGovernanceObjectVoteFile(const CGovernanceObjectVoteFile& other) : 16 62520 : nMemoryVotes(other.nMemoryVotes), 17 62520 : listVotes(other.listVotes), 18 62520 : mapVoteIndex() 19 62520 : { 20 62520 : RebuildIndex(); 21 125040 : } 22 : 23 1480 : void CGovernanceObjectVoteFile::AddVote(const CGovernanceVote& vote) 24 : { 25 1480 : uint256 nHash = vote.GetHash(); 26 : // make sure to never add/update already known votes 27 1480 : if (HasVote(nHash)) 28 0 : return; 29 1480 : listVotes.push_front(vote); 30 1480 : mapVoteIndex.emplace(nHash, listVotes.begin()); 31 1480 : ++nMemoryVotes; 32 1480 : RemoveOldVotes(vote); 33 1480 : } 34 : 35 4204 : bool CGovernanceObjectVoteFile::HasVote(const uint256& nHash) const 36 : { 37 4204 : return mapVoteIndex.find(nHash) != mapVoteIndex.end(); 38 : } 39 : 40 1224 : bool CGovernanceObjectVoteFile::SerializeVoteToStream(const uint256& nHash, CDataStream& ss) const 41 : { 42 1224 : auto it = mapVoteIndex.find(nHash); 43 1224 : if (it == mapVoteIndex.end()) { 44 0 : return false; 45 : } 46 1224 : ss << *(it->second); 47 1224 : return true; 48 1224 : } 49 : 50 1146 : std::vector<CGovernanceVote> CGovernanceObjectVoteFile::GetVotes() const 51 : { 52 1146 : std::vector<CGovernanceVote> vecResult; 53 1146 : vecResult.reserve(listVotes.size()); 54 1146 : std::copy(std::begin(listVotes), std::end(listVotes), std::back_inserter(vecResult)); 55 1146 : return vecResult; 56 1146 : } 57 : 58 0 : void CGovernanceObjectVoteFile::RemoveVotesFromMasternode(const COutPoint& outpointMasternode) 59 : { 60 0 : auto it = listVotes.begin(); 61 0 : while (it != listVotes.end()) { 62 0 : if (it->GetMasternodeOutpoint() == outpointMasternode) { 63 0 : --nMemoryVotes; 64 0 : mapVoteIndex.erase(it->GetHash()); 65 0 : listVotes.erase(it++); 66 0 : } else { 67 0 : ++it; 68 : } 69 : } 70 0 : } 71 : 72 0 : std::set<uint256> CGovernanceObjectVoteFile::RemoveInvalidVotes(const CDeterministicMNList& tip_mn_list, const COutPoint& outpointMasternode, bool fProposal) 73 : { 74 0 : std::set<uint256> removedVotes; 75 : 76 0 : auto it = listVotes.begin(); 77 0 : while (it != listVotes.end()) { 78 0 : if (it->GetMasternodeOutpoint() == outpointMasternode) { 79 0 : bool useVotingKey = fProposal && (it->GetSignal() == VOTE_SIGNAL_FUNDING); 80 0 : if (!it->IsValid(tip_mn_list, useVotingKey)) { 81 0 : removedVotes.emplace(it->GetHash()); 82 0 : --nMemoryVotes; 83 0 : mapVoteIndex.erase(it->GetHash()); 84 0 : listVotes.erase(it++); 85 0 : continue; 86 : } 87 0 : } 88 0 : ++it; 89 : } 90 : 91 0 : return removedVotes; 92 0 : } 93 : 94 1480 : void CGovernanceObjectVoteFile::RemoveOldVotes(const CGovernanceVote& vote) 95 : { 96 1480 : auto it = listVotes.begin(); 97 5880 : while (it != listVotes.end()) { 98 5880 : if (it->GetMasternodeOutpoint() == vote.GetMasternodeOutpoint() // same masternode 99 4400 : && it->GetParentHash() == vote.GetParentHash() // same governance object (e.g. same proposal) 100 1480 : && it->GetSignal() == vote.GetSignal() // same signal (e.g. "funding", "delete", etc.) 101 1480 : && it->GetTimestamp() < vote.GetTimestamp()) // older than new vote 102 : { 103 0 : --nMemoryVotes; 104 0 : mapVoteIndex.erase(it->GetHash()); 105 0 : listVotes.erase(it++); 106 0 : } else { 107 4400 : ++it; 108 : } 109 : } 110 1480 : } 111 : 112 62520 : void CGovernanceObjectVoteFile::RebuildIndex() 113 : { 114 62520 : mapVoteIndex.clear(); 115 62520 : nMemoryVotes = 0; 116 62520 : auto it = listVotes.begin(); 117 362435 : while (it != listVotes.end()) { 118 299915 : const CGovernanceVote& vote = *it; 119 299915 : uint256 nHash = vote.GetHash(); 120 299915 : if (mapVoteIndex.find(nHash) == mapVoteIndex.end()) { 121 299915 : mapVoteIndex[nHash] = it; 122 299915 : ++nMemoryVotes; 123 299915 : ++it; 124 299915 : } else { 125 0 : listVotes.erase(it++); 126 : } 127 : } 128 62520 : }