mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +01:00
Clear votes which were created before spork15 activation and use operator key for non-funding votes (#2512)
* Clear votes which were created before spork15 activation * Reject incoming votes which were created pre-DIP3 * Only use voting keys for VOTE_SIGNAL_FUNDING The other vote signals are meant to be emitted by sentinel and must thus be signed with the operator key. * Simplify GetMinVoteTime * Review suggestions/fixes * Add missing mutex in CGovernanceObject::RemoveOldVotes
This commit is contained in:
parent
f6f6d075dc
commit
0c1b683a06
@ -177,7 +177,7 @@ bool CGovernanceObject::ProcessVote(CNode* pfrom,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool onlyOwnerAllowed = nObjectType == GOVERNANCE_OBJECT_PROPOSAL;
|
bool onlyOwnerAllowed = nObjectType == GOVERNANCE_OBJECT_PROPOSAL && vote.GetSignal() == VOTE_SIGNAL_FUNDING;
|
||||||
|
|
||||||
// Finally check that the vote is actually valid (done last because of cost of signature verification)
|
// Finally check that the vote is actually valid (done last because of cost of signature verification)
|
||||||
if (!vote.IsValid(onlyOwnerAllowed)) {
|
if (!vote.IsValid(onlyOwnerAllowed)) {
|
||||||
@ -790,3 +790,21 @@ void CGovernanceObject::CheckOrphanVotes(CConnman& connman)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<uint256> CGovernanceObject::RemoveOldVotes(unsigned int nMinTime)
|
||||||
|
{
|
||||||
|
LOCK(cs);
|
||||||
|
|
||||||
|
auto removed = fileVotes.RemoveOldVotes(nMinTime);
|
||||||
|
|
||||||
|
if (!removed.empty()) {
|
||||||
|
std::string removedStr;
|
||||||
|
for (auto& h : removed) {
|
||||||
|
removedStr += strprintf(" %s\n", h.ToString());
|
||||||
|
}
|
||||||
|
LogPrintf("CGovernanceObject::RemoveOldVotes -- Removed %d old (pre-DIP3) votes for %s:\n%s\n", removed.size(), GetHash().ToString(), removedStr);
|
||||||
|
fDirtyCache = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
@ -350,6 +350,9 @@ private:
|
|||||||
void ClearMasternodeVotes();
|
void ClearMasternodeVotes();
|
||||||
|
|
||||||
void CheckOrphanVotes(CConnman& connman);
|
void CheckOrphanVotes(CConnman& connman);
|
||||||
|
|
||||||
|
// TODO can be removed after DIP3 is fully deployed
|
||||||
|
std::vector<uint256> RemoveOldVotes(unsigned int nMinTime);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,6 +68,23 @@ void CGovernanceObjectVoteFile::RemoveVotesFromMasternode(const COutPoint& outpo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<uint256> CGovernanceObjectVoteFile::RemoveOldVotes(unsigned int nMinTime)
|
||||||
|
{
|
||||||
|
std::vector<uint256> removed;
|
||||||
|
vote_l_it it = listVotes.begin();
|
||||||
|
while (it != listVotes.end()) {
|
||||||
|
if (it->GetTimestamp() < nMinTime) {
|
||||||
|
--nMemoryVotes;
|
||||||
|
removed.emplace_back(it->GetHash());
|
||||||
|
mapVoteIndex.erase(it->GetHash());
|
||||||
|
listVotes.erase(it++);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
|
||||||
void CGovernanceObjectVoteFile::RebuildIndex()
|
void CGovernanceObjectVoteFile::RebuildIndex()
|
||||||
{
|
{
|
||||||
mapVoteIndex.clear();
|
mapVoteIndex.clear();
|
||||||
|
@ -74,6 +74,9 @@ public:
|
|||||||
|
|
||||||
void RemoveVotesFromMasternode(const COutPoint& outpointMasternode);
|
void RemoveVotesFromMasternode(const COutPoint& outpointMasternode);
|
||||||
|
|
||||||
|
// TODO can be removed after full DIP3 deployment
|
||||||
|
std::vector<uint256> RemoveOldVotes(unsigned int nMinTime);
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS;
|
ADD_SERIALIZE_METHODS;
|
||||||
|
|
||||||
template <typename Stream, typename Operation>
|
template <typename Stream, typename Operation>
|
||||||
|
@ -222,6 +222,12 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, const std::string& strComm
|
|||||||
CGovernanceVote vote;
|
CGovernanceVote vote;
|
||||||
vRecv >> vote;
|
vRecv >> vote;
|
||||||
|
|
||||||
|
// TODO remove this check after full DIP3 deployment
|
||||||
|
if (vote.GetTimestamp() < GetMinVoteTime()) {
|
||||||
|
// Ignore votes pre-DIP3
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
uint256 nHash = vote.GetHash();
|
uint256 nHash = vote.GetHash();
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -573,6 +579,10 @@ void CGovernanceManager::DoMaintenance(CConnman& connman)
|
|||||||
{
|
{
|
||||||
if (fLiteMode || !masternodeSync.IsSynced() || ShutdownRequested()) return;
|
if (fLiteMode || !masternodeSync.IsSynced() || ShutdownRequested()) return;
|
||||||
|
|
||||||
|
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||||
|
ClearPreDIP3Votes();
|
||||||
|
}
|
||||||
|
|
||||||
// CHECK OBJECTS WE'VE ASKED FOR, REMOVE OLD ENTRIES
|
// CHECK OBJECTS WE'VE ASKED FOR, REMOVE OLD ENTRIES
|
||||||
|
|
||||||
CleanOrphanObjects();
|
CleanOrphanObjects();
|
||||||
@ -676,7 +686,7 @@ void CGovernanceManager::SyncSingleObjAndItsVotes(CNode* pnode, const uint256& n
|
|||||||
for (const auto& vote : fileVotes.GetVotes()) {
|
for (const auto& vote : fileVotes.GetVotes()) {
|
||||||
uint256 nVoteHash = vote.GetHash();
|
uint256 nVoteHash = vote.GetHash();
|
||||||
|
|
||||||
bool onlyOwnerAllowed = govobj.GetObjectType() == GOVERNANCE_OBJECT_PROPOSAL;
|
bool onlyOwnerAllowed = govobj.GetObjectType() == GOVERNANCE_OBJECT_PROPOSAL && vote.GetSignal() == VOTE_SIGNAL_FUNDING;
|
||||||
|
|
||||||
if (filter.contains(nVoteHash) || !vote.IsValid(onlyOwnerAllowed)) {
|
if (filter.contains(nVoteHash) || !vote.IsValid(onlyOwnerAllowed)) {
|
||||||
continue;
|
continue;
|
||||||
@ -1291,6 +1301,10 @@ void CGovernanceManager::UpdatedBlockTip(const CBlockIndex* pindex, CConnman& co
|
|||||||
nCachedBlockHeight = pindex->nHeight;
|
nCachedBlockHeight = pindex->nHeight;
|
||||||
LogPrint("gobject", "CGovernanceManager::UpdatedBlockTip -- nCachedBlockHeight: %d\n", nCachedBlockHeight);
|
LogPrint("gobject", "CGovernanceManager::UpdatedBlockTip -- nCachedBlockHeight: %d\n", nCachedBlockHeight);
|
||||||
|
|
||||||
|
if (deterministicMNManager->IsDeterministicMNsSporkActive(pindex->nHeight)) {
|
||||||
|
ClearPreDIP3Votes();
|
||||||
|
}
|
||||||
|
|
||||||
CheckPostponedObjects(connman);
|
CheckPostponedObjects(connman);
|
||||||
|
|
||||||
CSuperblockManager::ExecuteBestSuperblock(pindex->nHeight);
|
CSuperblockManager::ExecuteBestSuperblock(pindex->nHeight);
|
||||||
@ -1342,3 +1356,37 @@ void CGovernanceManager::CleanOrphanObjects()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int CGovernanceManager::GetMinVoteTime()
|
||||||
|
{
|
||||||
|
LOCK(cs_main);
|
||||||
|
if (!deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int64_t dip3SporkHeight = sporkManager.GetSporkValue(SPORK_15_DETERMINISTIC_MNS_ENABLED);
|
||||||
|
return chainActive[dip3SporkHeight]->nTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGovernanceManager::ClearPreDIP3Votes()
|
||||||
|
{
|
||||||
|
// This removes all votes which were created before DIP3 spork15 activation
|
||||||
|
// All these votes are invalid immediately after spork15 activation due to the introduction of voting keys, which
|
||||||
|
// are not equal to the old masternode private keys
|
||||||
|
|
||||||
|
unsigned int minVoteTime = GetMinVoteTime();
|
||||||
|
|
||||||
|
LOCK(cs);
|
||||||
|
for (auto& p : mapObjects) {
|
||||||
|
auto& obj = p.second;
|
||||||
|
auto removed = obj.RemoveOldVotes(minVoteTime);
|
||||||
|
if (removed.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (auto& voteHash : removed) {
|
||||||
|
cmapVoteToObject.Erase(voteHash);
|
||||||
|
cmapInvalidVotes.Erase(voteHash);
|
||||||
|
cmmapOrphanVotes.Erase(voteHash);
|
||||||
|
setRequestedVotes.erase(voteHash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -448,6 +448,10 @@ private:
|
|||||||
void RequestOrphanObjects(CConnman& connman);
|
void RequestOrphanObjects(CConnman& connman);
|
||||||
|
|
||||||
void CleanOrphanObjects();
|
void CleanOrphanObjects();
|
||||||
|
|
||||||
|
// TODO can be removed after full DIP3 deployment
|
||||||
|
unsigned int GetMinVoteTime();
|
||||||
|
void ClearPreDIP3Votes();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1086,7 +1086,7 @@ UniValue voteraw(const JSONRPCRequest& request)
|
|||||||
vote.SetTime(nTime);
|
vote.SetTime(nTime);
|
||||||
vote.SetSignature(vchSig);
|
vote.SetSignature(vchSig);
|
||||||
|
|
||||||
bool onlyOwnerAllowed = govObjType == GOVERNANCE_OBJECT_PROPOSAL;
|
bool onlyOwnerAllowed = govObjType == GOVERNANCE_OBJECT_PROPOSAL && vote.GetSignal() == VOTE_SIGNAL_FUNDING;
|
||||||
|
|
||||||
if (!vote.IsValid(onlyOwnerAllowed)) {
|
if (!vote.IsValid(onlyOwnerAllowed)) {
|
||||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Failure to verify vote.");
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "Failure to verify vote.");
|
||||||
|
Loading…
Reference in New Issue
Block a user