From 487674f0c9c1ec8b6c2c8ae2073206992acb406f Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Tue, 31 May 2016 14:22:01 -0700 Subject: [PATCH 1/9] Governance object/vote syncing fixes - disable fCached values - use two maps for storing votes, by hash and parent-hash/type - disable part of flatdb.dump (still overwriting) - fixed govobj/votes relay and sync --- src/flat-database.h | 20 ++ src/governance-vote.cpp | 4 +- src/governance-vote.h | 14 ++ src/governance.cpp | 356 ++++++++++++++++------------------- src/governance.h | 38 +++- src/main.cpp | 86 ++++++--- src/masternode-sync.cpp | 143 ++++++++------ src/masternode-sync.h | 7 +- src/net.cpp | 1 + src/protocol.cpp | 10 +- src/protocol.h | 8 +- src/rpcmasternode-budget.cpp | 5 - src/rpcmisc.cpp | 10 +- src/version.h | 10 +- 14 files changed, 400 insertions(+), 312 deletions(-) diff --git a/src/flat-database.h b/src/flat-database.h index d24e04b112f10..6b1b0038e7769 100644 --- a/src/flat-database.h +++ b/src/flat-database.h @@ -197,6 +197,26 @@ class CFlatDB { int64_t nStart = GetTimeMillis(); + + // LOAD SERIALIZED FILE TO DETERMINE SAFETY OF SAVING INTO THAT FILE + + /* + + + 2016-06-02 21:23:55 dash-shutoff | Governance Objects: 1, Seen Budgets: 1, Seen Budget Votes: 0, Vote Count: 0 + 2016-06-02 21:23:55 dash-shutoff | Governance Objects: 1, Seen Budgets: 0, Seen Budget Votes: 0, Vote Count: 0 + 2016-06-02 21:29:17 dashd | Governance Objects: 1, Seen Budgets: 0, Seen Budget Votes: 0, Vote Count: 0 + 2016-06-02 21:29:17 dashd | CFlatDB - Governance Objects: 1, Seen Budgets: 0, Seen Budget Votes: 0, Vote Count: 0 + 2016-06-02 21:29:25 dash-shutoff | Governance Objects: 1, Seen Budgets: 0, Seen Budget Votes: 0, Vote Count: 0 + 2016-06-02 21:30:07 dash-shutoff | Governance Objects: 1, Seen Budgets: 1, Seen Budget Votes: 0, Vote Count: 0 + 2016-06-02 21:30:16 dashd | Governance Objects: 1, Seen Budgets: 1, Seen Budget Votes: 0, Vote Count: 0 + 2016-06-02 21:30:16 dashd | CFlatDB - Governance Objects: 1, Seen Budgets: 1, Seen Budget Votes: 0, Vote Count: 0 + + + This fact can be demonstrated by adding a governance item, then stopping and starting the client. + With the code enabled, "Seen Budgets" will equal 0, whereas the object should have one entry. + */ + LogPrintf("Verifying %s format...\n", strFilename); T tmpObjToLoad; ReadResult readResult = Read(tmpObjToLoad, true); diff --git a/src/governance-vote.cpp b/src/governance-vote.cpp index 62d2aee4e78f8..6065fa4cfbfb1 100644 --- a/src/governance-vote.cpp +++ b/src/governance-vote.cpp @@ -43,8 +43,8 @@ CGovernanceVote::CGovernanceVote(CTxIn vinMasternodeIn, uint256 nParentHashIn, i void CGovernanceVote::Relay() { - CInv inv(MSG_BUDGET_VOTE, GetHash()); - RelayInv(inv, MIN_BUDGET_PEER_PROTO_VERSION); + CInv inv(MSG_GOVERNANCE_VOTE, GetHash()); + RelayInv(inv, MSG_GOVERNANCE_PEER_PROTO_VERSION); } bool CGovernanceVote::Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode) diff --git a/src/governance-vote.h b/src/governance-vote.h index 2318a421b08b0..36b9eed633f10 100644 --- a/src/governance-vote.h +++ b/src/governance-vote.h @@ -86,6 +86,20 @@ class CGovernanceVote return ss.GetHash(); } + // GET HASH WITH DETERMINISTIC HASH OF PARENT-HASH/VOTE-TYPE + uint256 GetTypeHash() + { + // CALCULATE HOW TO STORE VOTE IN governance.mapVotes + + CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); + ss << vinMasternode; + ss << nParentHash; + ss << nVoteSignal; + ss << nVoteOutcome; + // -- timeless + return ss.GetHash(); + } + uint256 GetParentHash(){ return nParentHash; } diff --git a/src/governance.cpp b/src/governance.cpp index 5568372c07480..0f0572ffc4ed3 100644 --- a/src/governance.cpp +++ b/src/governance.cpp @@ -33,7 +33,6 @@ bool IsCollateralValid(uint256 nTxCollateralHash, uint256 nExpectedHash, std::st CTransaction txCollateral; uint256 nBlockHash; - int64_t nTime; // RETRIEVE TRANSACTION IN QUESTION @@ -80,7 +79,6 @@ bool IsCollateralValid(uint256 nTxCollateralHash, uint256 nExpectedHash, std::st CBlockIndex* pindex = (*mi).second; if (chainActive.Contains(pindex)) { nConfirmationsIn += chainActive.Height() - pindex->nHeight + 1; - nTime = pindex->nTime; } } } @@ -99,6 +97,116 @@ bool IsCollateralValid(uint256 nTxCollateralHash, uint256 nExpectedHash, std::st return true; } +void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv) +{ + // lite mode is not supported + if(fLiteMode) return; + if(!masternodeSync.IsBlockchainSynced()) return; + + LOCK(cs_budget); + + // GOVERANCE SYNCING FUNCTIONALITY + + if (strCommand == NetMsgType::MNGOVERNANCESYNC) { + uint256 nProp; + vRecv >> nProp; + + if(Params().NetworkIDString() == CBaseChainParams::MAIN){ + if(nProp == uint256()) { + if(pfrom->HasFulfilledRequest(NetMsgType::MNGOVERNANCESYNC)) { + LogPrint("mngovernance", "peer already asked me for the list\n"); + Misbehaving(pfrom->GetId(), 20); + return; + } + pfrom->FulfilledRequest(NetMsgType::MNGOVERNANCESYNC); + } + } + + // ask for a specific proposal and it's votes + Sync(pfrom, nProp); + LogPrint("mngovernance", "syncing governance objects to our peer at %s\n", pfrom->addr.ToString()); + } + + // NEW GOVERNANCE OBJECT + + if (strCommand == NetMsgType::MNGOVERNANCEOBJECT) { + CGovernanceObject govobj; + vRecv >> govobj; + + if(mapSeenGovernanceObjects.count(govobj.GetHash())){ + // TODO - print error code? what if it's GOVOBJ_ERROR_IMMATURE? + masternodeSync.AddedBudgetItem(govobj.GetHash()); + return; + } + + std::string strError = ""; + int nConf = 0; + if(!IsCollateralValid(govobj.nFeeTXHash, govobj.GetHash(), strError, nConf, GOVERNANCE_FEE_TX)){ + LogPrintf("Governance object collateral tx is not valid - %s - %s\n", govobj.nFeeTXHash.ToString(), strError); + //todo 12.1 + //if(nConf >= 1) vecImmatureGovernanceObjects.push_back(govobj); + return; + } + + if(!govobj.IsValid(pCurrentBlockIndex, strError)) { + mapSeenGovernanceObjects.insert(make_pair(govobj.GetHash(), SEEN_OBJECT_ERROR_INVALID)); + LogPrintf("Governance object is invalid - %s\n", strError); + return; + } + + if(AddGovernanceObject(govobj)) + { + govobj.Relay(); + } + + mapSeenGovernanceObjects.insert(make_pair(govobj.GetHash(), SEEN_OBJECT_IS_VALID)); + masternodeSync.AddedBudgetItem(govobj.GetHash()); + + LogPrintf("Governance object - new! - %s\n", govobj.GetHash().ToString()); + //We might have active votes for this proposal that are valid now + CheckOrphanVotes(); + } + + // NEW GOVERNANCE OBJECT VOTE + + if (strCommand == NetMsgType::MNGOVERNANCEVOTE) { + CGovernanceVote vote; + vRecv >> vote; + vote.fValid = true; + + if(mapSeenVotes.count(vote.GetHash())){ + masternodeSync.AddedBudgetItem(vote.GetHash()); + return; + } + + CMasternode* pmn = mnodeman.Find(vote.vinMasternode); + if(pmn == NULL) { + LogPrint("mngovernance", "mngovernance - unknown masternode - vin: %s\n", vote.vinMasternode.ToString()); + mnodeman.AskForMN(pfrom, vote.vinMasternode); + return; + } + + mapSeenVotes.insert(make_pair(vote.GetHash(), SEEN_OBJECT_IS_VALID)); + if(!vote.IsValid(true)){ + LogPrintf("mngovernance - signature invalid\n"); + if(masternodeSync.IsSynced()) Misbehaving(pfrom->GetId(), 20); + // it could just be a non-synced masternode + mnodeman.AskForMN(pfrom, vote.vinMasternode); + return; + } + + std::string strError = ""; + if(UpdateGovernanceObject(vote, pfrom, strError)) { + vote.Relay(); + masternodeSync.AddedBudgetItem(vote.GetHash()); + } + + LogPrint("mngovernance", "new vote - %s\n", vote.GetHash().ToString()); + } + +} + + void CGovernanceManager::CheckOrphanVotes() { LOCK(cs); @@ -171,16 +279,17 @@ void CGovernanceManager::CheckAndRemove() CGovernanceObject *CGovernanceManager::FindGovernanceObject(const std::string &strName) { - //find the prop with the highest yes count + // find the prop with the highest yes count int nYesCount = -99999; CGovernanceObject* pGovObj = NULL; std::map::iterator it = mapObjects.begin(); while(it != mapObjects.end()){ - if((*it).second.strName == strName && (*it).second.GetYesCount(VOTE_SIGNAL_FUNDING) > nYesCount){ - pGovObj = &((*it).second); - nYesCount = pGovObj->GetYesCount(VOTE_SIGNAL_FUNDING); + pGovObj = &((*it).second); + int nGovObjYesCount = pGovObj->GetYesCount(VOTE_SIGNAL_FUNDING); + if((*it).second.strName == strName && nGovObjYesCount > nYesCount){ + nYesCount = nGovObjYesCount; } ++it; } @@ -190,7 +299,7 @@ CGovernanceObject *CGovernanceManager::FindGovernanceObject(const std::string &s return pGovObj; } -CGovernanceObject *CGovernanceManager::FindGovernanceObject(uint256 nHash) +CGovernanceObject *CGovernanceManager::FindGovernanceObject(uint256& nHash) { LOCK(cs); @@ -243,7 +352,7 @@ void CGovernanceManager::NewBlock() if(!pCurrentBlockIndex) return; // todo - 12.1 - add govobj sync - if (masternodeSync.RequestedMasternodeAssets <= MASTERNODE_SYNC_BUDGET) return; + if (masternodeSync.RequestedMasternodeAssets <= MASTERNODE_SYNC_GOVERNANCE) return; //this function should be called 1/6 blocks, allowing up to 100 votes per day on all proposals if(pCurrentBlockIndex->nHeight % 6 != 0) return; @@ -269,7 +378,7 @@ void CGovernanceManager::NewBlock() // LOCK(cs_vNodes); // BOOST_FOREACH(CNode* pnode, vNodes) - // if(pnode->nVersion >= MIN_BUDGET_PEER_PROTO_VERSION) + // if(pnode->nVersion >= MSG_GOVERNANCE_PEER_PROTO_VERSION) // Sync(pnode, uint256()); // MarkSynced(); @@ -320,171 +429,27 @@ void CGovernanceManager::NewBlock() } -void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv) -{ - // lite mode is not supported - if(fLiteMode) return; - if(!masternodeSync.IsBlockchainSynced()) return; - - LOCK(cs_budget); - - if (strCommand == NetMsgType::MNGOVERNANCEVOTESYNC) { //Masternode vote sync - uint256 nProp; - vRecv >> nProp; - - if(Params().NetworkIDString() == CBaseChainParams::MAIN){ - if(nProp == uint256()) { - if(pfrom->HasFulfilledRequest(NetMsgType::MNGOVERNANCEVOTESYNC)) { - LogPrintf("mnvs - peer already asked me for the list\n"); - Misbehaving(pfrom->GetId(), 20); - return; - } - pfrom->FulfilledRequest(NetMsgType::MNGOVERNANCEVOTESYNC); - } - } - - // ask for a specific proposal and it's votes - Sync(pfrom, nProp); - LogPrintf("mnvs - Sent Masternode votes to %s\n", pfrom->addr.ToString()); - } - - if (strCommand == NetMsgType::MNGOVERNANCEPROPOSAL) { //Masternode Proposal - CGovernanceObject govobj; - vRecv >> govobj; - - if(mapSeenGovernanceObjects.count(govobj.GetHash())){ - // TODO - print error code? what if it's GOVOBJ_ERROR_IMMATURE? - masternodeSync.AddedBudgetItem(govobj.GetHash()); - return; - } - - std::string strError = ""; - int nConf = 0; - if(!IsCollateralValid(govobj.nFeeTXHash, govobj.GetHash(), strError, nConf, GOVERNANCE_FEE_TX)){ - LogPrintf("Proposal FeeTX is not valid - %s - %s\n", govobj.nFeeTXHash.ToString(), strError); - //todo 12.1 - //if(nConf >= 1) vecImmatureGovernanceObjects.push_back(govobj); - return; - } - - if(!govobj.IsValid(pCurrentBlockIndex, strError)) { - mapSeenGovernanceObjects.insert(make_pair(govobj.GetHash(), SEEN_OBJECT_ERROR_INVALID)); - LogPrintf("mprop - invalid budget proposal - %s\n", strError); - return; - } - - if(AddGovernanceObject(govobj)) - { - govobj.Relay(); - } - mapSeenGovernanceObjects.insert(make_pair(govobj.GetHash(), SEEN_OBJECT_IS_VALID)); - masternodeSync.AddedBudgetItem(govobj.GetHash()); - - LogPrintf("mprop - new budget - %s\n", govobj.GetHash().ToString()); - //We might have active votes for this proposal that are valid now - CheckOrphanVotes(); - } - - if (strCommand == NetMsgType::MNGOVERNANCEVOTE) { //Masternode Vote - CGovernanceVote vote; - vRecv >> vote; - vote.fValid = true; - - if(mapSeenVotes.count(vote.GetHash())){ - masternodeSync.AddedBudgetItem(vote.GetHash()); - return; - } - - CMasternode* pmn = mnodeman.Find(vote.vinMasternode); - if(pmn == NULL) { - LogPrint("mngovernance", "mvote - unknown masternode - vin: %s\n", vote.vinMasternode.ToString()); - mnodeman.AskForMN(pfrom, vote.vinMasternode); - return; - } - - mapSeenVotes.insert(make_pair(vote.GetHash(), SEEN_OBJECT_IS_VALID)); - if(!vote.IsValid(true)){ - LogPrintf("mvote - signature invalid\n"); - if(masternodeSync.IsSynced()) Misbehaving(pfrom->GetId(), 20); - // it could just be a non-synced masternode - mnodeman.AskForMN(pfrom, vote.vinMasternode); - return; - } - - std::string strError = ""; - if(UpdateGovernanceObject(vote, pfrom, strError)) { - vote.Relay(); - masternodeSync.AddedBudgetItem(vote.GetHash()); - } - - LogPrintf("mvote - new budget vote - %s\n", vote.GetHash().ToString()); - } - -} - -// description: incremental sync with our peers -// note: incremental syncing seems excessive, well just have clients ask for specific objects and their votes -// note: 12.1 - remove -// void CGovernanceManager::ResetSync() -// { -// LOCK(cs); - -// std::map >::iterator it1 = mapVotes.begin(); -// while(it1 != mapVotes.end()){ -// (*it1).second.second.fSynced = false; -// ++it1; -// } -// } - -// description: incremental sync with our peers -// note: incremental syncing seems excessive, well just have clients ask for specific objects and their votes -// note: 12.1 - remove -// void CGovernanceManager::MarkSynced() -// { -// LOCK(cs); - -// /* -// Mark that we've sent all valid items -// */ - -// // this could screw up syncing, so let's log it -// LogPrintf("CGovernanceManager::MarkSynced\n"); - -// std::map >::iterator it1 = mapVotes.begin(); -// while(it1 != mapVotes.end()){ -// if((*it1).second.second.fValid) -// (*it1).second.second.fSynced = true; -// ++it1; -// } -// } - - void CGovernanceManager::Sync(CNode* pfrom, uint256 nProp) { LOCK(cs); /* - note 12.1 - fix comments below - - Sync with a client on the network - - -- - This code checks each of the hash maps for all known budget proposals and finalized budget proposals, then checks them against the budget object to see if they're OK. If all checks pass, we'll send it to the peer. - */ int nInvCount = 0; // SYNC GOVERNANCE OBJECTS WITH OTHER CLIENT - std::map::iterator it1 = mapSeenGovernanceObjects.begin(); - while(it1 != mapSeenGovernanceObjects.end()){ - CGovernanceObject* pGovObj = FindGovernanceObject((*it1).first); - if(pGovObj && pGovObj->fCachedValid && ((nProp == uint256() || ((*it1).first == nProp)))){ + std::map::iterator it1 = mapObjects.begin(); + while(it1 != mapObjects.end()) + { + uint256 h = (*it1).first; + + if((*it1).second.fCachedValid && ((nProp == uint256() || (h == nProp)))){ // Push the inventory budget proposal message over to the other client - pfrom->PushInventory(CInv(MSG_BUDGET_PROPOSAL, (*it1).first)); + pfrom->PushInventory(CInv(MSG_GOVERNANCE_OBJECT, h)); nInvCount++; } ++it1; @@ -492,18 +457,26 @@ void CGovernanceManager::Sync(CNode* pfrom, uint256 nProp) // SYNC OUR GOVERNANCE OBJECT VOTES WITH THEIR GOVERNANCE OBJECT VOTES - std::map::iterator it2 = mapVotes.begin(); - while(it2 != mapVotes.end()){ - pfrom->PushInventory(CInv(MSG_BUDGET_VOTE, (*it2).first)); + std::map::iterator it2 = mapVotesByHash.begin(); + while(it2 != mapVotesByHash.end()) + { + pfrom->PushInventory(CInv(MSG_GOVERNANCE_VOTE, (*it2).first)); nInvCount++; ++it2; } - pfrom->PushMessage(NetMsgType::SYNCSTATUSCOUNT, MASTERNODE_SYNC_BUDGET_PROP, nInvCount); - + pfrom->PushMessage(NetMsgType::SYNCSTATUSCOUNT, MASTERNODE_SYNC_GOVOBJ, nInvCount); LogPrintf("CGovernanceManager::Sync - sent %d items\n", nInvCount); } +void CGovernanceManager::SyncParentObjectByVote(CNode* pfrom, CGovernanceVote& vote) +{ + if(!mapAskedForGovernanceObject.count(vote.nParentHash)){ + pfrom->PushMessage(NetMsgType::MNGOVERNANCESYNC, vote.nParentHash); + mapAskedForGovernanceObject[vote.nParentHash] = GetTime(); + } +} + bool CGovernanceManager::UpdateGovernanceObject(CGovernanceVote& vote, CNode* pfrom, std::string& strError) { LOCK(cs); @@ -514,16 +487,13 @@ bool CGovernanceManager::UpdateGovernanceObject(CGovernanceVote& vote, CNode* pf // otherwise we'll think a full sync succeeded when they return a result if(!masternodeSync.IsSynced()) return false; - LogPrintf("CGovernanceManager::UpdateGovernanceObject - Unknown proposal %d, asking for source proposal\n", vote.nParentHash.ToString()); + LogPrintf("CGovernanceManager::UpdateGovernanceObject - Unknown object %d, asking for source\n", vote.nParentHash.ToString()); mapOrphanVotes[vote.nParentHash] = vote; - if(!mapAskedForGovernanceObject.count(vote.nParentHash)){ - pfrom->PushMessage(NetMsgType::MNGOVERNANCEVOTESYNC, vote.nParentHash); - mapAskedForGovernanceObject[vote.nParentHash] = GetTime(); - } + SyncParentObjectByVote(pfrom, vote); } - strError = "Proposal not found!"; + strError = "Governance object not found!"; return false; } @@ -535,25 +505,25 @@ bool CGovernanceManager::AddOrUpdateVote(CGovernanceVote& vote, std::string& str { LOCK(cs); - // store newest vote per action - arith_uint256 a = UintToArith256(vote.nParentHash) + vote.nVoteSignal; - uint256 hash2 = ArithToUint256(a); + // GET DETERMINISTIC HASH INCLUDING PARENT/TYPE + uint256 hash = vote.GetTypeHash(); - if(mapVotes.count(hash2)) + if(mapVotesByType.count(hash)) { - if(mapVotes[hash2].nTime > vote.nTime){ + if(mapVotesByType[hash].nTime > vote.nTime){ strError = strprintf("new vote older than existing vote - %s", vote.GetHash().ToString()); LogPrint("mngovernance", "CGovernanceObject::AddOrUpdateVote - %s\n", strError); return false; } - if(vote.nTime - mapVotes[hash2].nTime < GOVERNANCE_UPDATE_MIN){ - strError = strprintf("time between votes is too soon - %s - %lli", vote.GetHash().ToString(), vote.nTime - mapVotes[hash2].nTime); + if(vote.nTime - mapVotesByType[hash].nTime < GOVERNANCE_UPDATE_MIN){ + strError = strprintf("time between votes is too soon - %s - %lli", vote.GetHash().ToString(), vote.nTime - mapVotesByType[hash].nTime); LogPrint("mngovernance", "CGovernanceObject::AddOrUpdateVote - %s\n", strError); return false; } } - mapVotes[hash2] = vote; + mapVotesByType[vote.GetTypeHash()] = vote; + mapVotesByHash[vote.GetHash()] = vote; return true; } @@ -597,7 +567,7 @@ CGovernanceObject::CGovernanceObject(const CGovernanceObject& other) bool CGovernanceObject::IsValid(const CBlockIndex* pindex, std::string& strError, bool fCheckCollateral) { - if(GetNoCount(VOTE_SIGNAL_VALID) - GetYesCount(VOTE_SIGNAL_VALID) > mnodeman.CountEnabled(MIN_BUDGET_PEER_PROTO_VERSION)/10){ + if(GetNoCount(VOTE_SIGNAL_VALID) - GetYesCount(VOTE_SIGNAL_VALID) > mnodeman.CountEnabled(MSG_GOVERNANCE_PEER_PROTO_VERSION)/10){ strError = "Automated removal"; return false; } @@ -618,12 +588,12 @@ bool CGovernanceObject::IsValid(const CBlockIndex* pindex, std::string& strError // } if(strName.size() > 20) { - strError = "Invalid proposal name, limit of 20 characters."; + strError = "Invalid object name, limit of 20 characters."; return false; } if(strName != SanitizeString(strName)) { - strError = "Invalid proposal name, unsafe characters found."; + strError = "Invalid object name, unsafe characters found."; return false; } @@ -665,13 +635,13 @@ void CGovernanceManager::CleanAndRemove(bool fSignatureCheck) * */ - // std::map::iterator it2 = mapVotes.begin(); - // while(it2 != mapVotes.end()){ + // std::map::iterator it2 = mapVotesByHash.begin(); + // while(it2 != mapVotesByHash.end()){ // if(!(*it2).second.IsValid(fSignatureCheck)) // { // // 12.1 - log to specialized handle (govobj?) // LogPrintf("CGovernanceManager::CleanAndRemove - Proposal/Budget is known, activating and removing orphan vote\n"); - // mapVotes.erase(it2++); + // mapVotesByHash.erase(it2++); // } else { // ++it2; // } @@ -687,6 +657,11 @@ int CGovernanceObject::GetAbsoluteYesCount(int nVoteSignalIn) return governance.CountMatchingVotes((*this), nVoteSignalIn, VOTE_OUTCOME_YES) - governance.CountMatchingVotes((*this), nVoteSignalIn, VOTE_OUTCOME_NO); } +int CGovernanceObject::GetAbsoluteNoCount(int nVoteSignalIn) +{ + return governance.CountMatchingVotes((*this), nVoteSignalIn, VOTE_OUTCOME_NO) - governance.CountMatchingVotes((*this), nVoteSignalIn, VOTE_OUTCOME_YES); +} + int CGovernanceObject::GetYesCount(int nVoteSignalIn) { return governance.CountMatchingVotes((*this), nVoteSignalIn, VOTE_OUTCOME_YES); @@ -704,8 +679,8 @@ int CGovernanceObject::GetAbstainCount(int nVoteSignalIn) void CGovernanceObject::Relay() { - CInv inv(MSG_BUDGET_PROPOSAL, GetHash()); - RelayInv(inv, MIN_BUDGET_PEER_PROTO_VERSION); + CInv inv(MSG_GOVERNANCE_OBJECT, GetHash()); + RelayInv(inv, MSG_GOVERNANCE_PEER_PROTO_VERSION); } std::string CGovernanceManager::ToString() const @@ -715,7 +690,8 @@ std::string CGovernanceManager::ToString() const info << "Governance Objects: " << (int)mapObjects.size() << ", Seen Budgets: " << (int)mapSeenGovernanceObjects.size() << ", Seen Budget Votes: " << (int)mapSeenVotes.size() << - ", Vote Count: " << (int)mapVotes.size(); + ", VoteByHash Count: " << (int)mapVotesByHash.size() << + ", VoteByType Count: " << (int)mapVotesByType.size(); return info.str(); } @@ -739,8 +715,8 @@ int CGovernanceManager::CountMatchingVotes(CGovernanceObject& govobj, int nVoteS int nCount = 0; - std::map::iterator it2 = mapVotes.begin(); - while(it2 != mapVotes.end()){ + std::map::iterator it2 = mapVotesByHash.begin(); + while(it2 != mapVotesByHash.end()){ if((*it2).second.fValid && (*it2).second.nVoteSignal == nVoteSignalIn && (*it2).second.GetParentHash() == govobj.GetHash()) { nCount += ((*it2).second.nVoteOutcome == nVoteOutcomeIn ? 1 : 0); diff --git a/src/governance.h b/src/governance.h index 8ab56d0a8e81b..8f6564bd4725c 100644 --- a/src/governance.h +++ b/src/governance.h @@ -70,7 +70,11 @@ class CGovernanceManager std::map mapSeenGovernanceObjects; std::map mapSeenVotes; std::map mapOrphanVotes; - std::map mapVotes; + + // todo: one of these should point to the other + // -- must be carefully managed while adding/removing/updating + std::map mapVotesByHash; + std::map mapVotesByType; CGovernanceManager() { mapObjects.clear(); @@ -94,12 +98,13 @@ class CGovernanceManager //void ResetSync(); //void MarkSynced(); void Sync(CNode* node, uint256 nProp); + void SyncParentObjectByVote(CNode* pfrom, CGovernanceVote& vote); void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv); void NewBlock(); CGovernanceObject *FindGovernanceObject(const std::string &strName); - CGovernanceObject *FindGovernanceObject(uint256 nHash); + CGovernanceObject *FindGovernanceObject(uint256& nHash); std::vector GetAllProposals(int64_t nMoreThanTime); @@ -122,6 +127,8 @@ class CGovernanceManager mapSeenGovernanceObjects.clear(); mapSeenVotes.clear(); mapOrphanVotes.clear(); + mapVotesByType.clear(); + mapVotesByHash.clear(); } std::string ToString() const; @@ -133,7 +140,8 @@ class CGovernanceManager READWRITE(mapSeenVotes); READWRITE(mapOrphanVotes); READWRITE(mapObjects); - READWRITE(mapVotes); + READWRITE(mapVotesByHash); + READWRITE(mapVotesByType); } void UpdatedBlockTip(const CBlockIndex *pindex); @@ -185,21 +193,32 @@ class CGovernanceObject // CALCULATE MINIMUM SUPPORT LEVELS REQUIRED int nMnCount = mnodeman.CountEnabled(); + if(nMnCount == 0) return; + + // CALCULATE THE MINUMUM VOTE COUNT REQUIRED FOR FULL SIGNAL + int nAbsYesVoteReq = nMnCount / 10; + int nAbsNoVoteReq = nAbsYesVoteReq; //same in absolute value // SET SENTINEL FLAGS TO FALSE fCachedFunding = false; - fCachedValid = false; + fCachedValid = true; //default to valid fCachedDelete = false; fCachedEndorsed = false; // SET SENTINEL FLAGS TO TRUE IF MIMIMUM SUPPORT LEVELS ARE REACHED - if(GetAbsoluteYesCount(VOTE_SIGNAL_FUNDING) >= nAbsYesVoteReq) fCachedFunding = true; - if(GetAbsoluteYesCount(VOTE_SIGNAL_VALID) >= nAbsYesVoteReq) fCachedValid = true; - if(GetAbsoluteYesCount(VOTE_SIGNAL_DELETE) >= nAbsYesVoteReq) fCachedDelete = true; - if(GetAbsoluteYesCount(VOTE_SIGNAL_ENDORSED) >= nAbsYesVoteReq) fCachedEndorsed = true; + // todo - 12.1 + // if(GetAbsoluteYesCount(VOTE_SIGNAL_FUNDING) >= nAbsYesVoteReq) fCachedFunding = true; + // if(GetAbsoluteYesCount(VOTE_SIGNAL_VALID) >= nAbsYesVoteReq) fCachedValid = true; + // if(GetAbsoluteYesCount(VOTE_SIGNAL_DELETE) >= nAbsYesVoteReq) fCachedDelete = true; + // if(GetAbsoluteYesCount(VOTE_SIGNAL_ENDORSED) >= nAbsYesVoteReq) fCachedEndorsed = true; + + // if(GetAbsoluteNoCount(VOTE_SIGNAL_FUNDING) >= nAbsNoVoteReq) fCachedFunding = false; + // if(GetAbsoluteNoCount(VOTE_SIGNAL_VALID) >= nAbsNoVoteReq) fCachedValid = false; + // if(GetAbsoluteNoCount(VOTE_SIGNAL_DELETE) >= nAbsNoVoteReq) fCachedDelete = false; + // if(GetAbsoluteNoCount(VOTE_SIGNAL_ENDORSED) >= nAbsNoVoteReq) fCachedEndorsed = false; } void swap(CGovernanceObject& first, CGovernanceObject& second) // nothrow @@ -230,6 +249,7 @@ class CGovernanceObject // get vote counts on each outcome int GetAbsoluteYesCount(int nVoteSignalIn); + int GetAbsoluteNoCount(int nVoteSignalIn); int GetYesCount(int nVoteSignalIn); int GetNoCount(int nVoteSignalIn); int GetAbstainCount(int nVoteSignalIn); @@ -258,7 +278,7 @@ class CGovernanceObject * SetData - Example usage: * -------------------------------------------------------- * - * dash-core is data-agnostic, for rules about data see sentinel documentation + * Governance is data-agnostic, for rules about data see sentinel documentation * */ diff --git a/src/main.cpp b/src/main.cpp index 1e7d196da14f7..b2a77bc4ab0ad 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4354,11 +4354,11 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main) case MSG_MASTERNODE_WINNER: return mnpayments.mapMasternodePayeeVotes.count(inv.hash); - case MSG_BUDGET_VOTE: - return governance.mapSeenVotes.count(inv.hash); + case MSG_GOVERNANCE_VOTE: + return governance.mapVotesByHash.count(inv.hash); - case MSG_BUDGET_PROPOSAL: - return governance.mapSeenGovernanceObjects.count(inv.hash); + case MSG_GOVERNANCE_OBJECT: + return governance.mapObjects.count(inv.hash); case MSG_MASTERNODE_ANNOUNCE: return mnodeman.mapSeenMasternodeBroadcast.count(inv.hash); @@ -4479,9 +4479,12 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam pushed = true; } } - if (!pushed && inv.type == MSG_TX) { + + if (!pushed && inv.type == MSG_TX) + { CTransaction tx; - if (mempool.lookup(inv.hash, tx)) { + if (mempool.lookup(inv.hash, tx)) + { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(1000); ss << tx; @@ -4489,8 +4492,11 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam pushed = true; } } - if (!pushed && inv.type == MSG_TXLOCK_VOTE) { - if(mapTxLockVote.count(inv.hash)){ + + if (!pushed && inv.type == MSG_TXLOCK_VOTE) + { + if(mapTxLockVote.count(inv.hash)) + { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(1000); ss << mapTxLockVote[inv.hash]; @@ -4498,8 +4504,11 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam pushed = true; } } - if (!pushed && inv.type == MSG_TXLOCK_REQUEST) { - if(mapTxLockReq.count(inv.hash)){ + + if (!pushed && inv.type == MSG_TXLOCK_REQUEST) + { + if(mapTxLockReq.count(inv.hash)) + { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(1000); ss << mapTxLockReq[inv.hash]; @@ -4507,8 +4516,11 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam pushed = true; } } - if (!pushed && inv.type == MSG_SPORK) { - if(mapSporks.count(inv.hash)){ + + if (!pushed && inv.type == MSG_SPORK) + { + if(mapSporks.count(inv.hash)) + { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(1000); ss << mapSporks[inv.hash]; @@ -4516,8 +4528,11 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam pushed = true; } } - if (!pushed && inv.type == MSG_MASTERNODE_WINNER) { - if(mnpayments.mapMasternodePayeeVotes.count(inv.hash)){ + + if (!pushed && inv.type == MSG_MASTERNODE_WINNER) + { + if(mnpayments.mapMasternodePayeeVotes.count(inv.hash)) + { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(1000); ss << mnpayments.mapMasternodePayeeVotes[inv.hash]; @@ -4525,22 +4540,27 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam pushed = true; } } - if (!pushed && inv.type == MSG_BUDGET_VOTE) { - if(governance.mapSeenVotes.count(inv.hash)){ + + if (!pushed && inv.type == MSG_GOVERNANCE_VOTE) + { + if(governance.mapVotesByHash.count(inv.hash)) + { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(1000); - ss << governance.mapSeenVotes[inv.hash]; + ss << governance.mapVotesByHash[inv.hash]; pfrom->PushMessage(NetMsgType::MNGOVERNANCEVOTE, ss); pushed = true; } } - if (!pushed && inv.type == MSG_BUDGET_PROPOSAL) { - if(governance.mapSeenGovernanceObjects.count(inv.hash)){ + if (!pushed && inv.type == MSG_GOVERNANCE_OBJECT) + { + if(governance.mapObjects.count(inv.hash)) + { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(1000); - ss << governance.mapSeenGovernanceObjects[inv.hash]; - pfrom->PushMessage(NetMsgType::MNGOVERNANCEPROPOSAL, ss); + ss << governance.mapObjects[inv.hash]; + pfrom->PushMessage(NetMsgType::MNGOVERNANCEOBJECT, ss); pushed = true; } } @@ -4555,8 +4575,10 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } } - if (!pushed && inv.type == MSG_MASTERNODE_PING) { - if(mnodeman.mapSeenMasternodePing.count(inv.hash)){ + if (!pushed && inv.type == MSG_MASTERNODE_PING) + { + if(mnodeman.mapSeenMasternodePing.count(inv.hash)) + { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(1000); ss << mnodeman.mapSeenMasternodePing[inv.hash]; @@ -4565,8 +4587,10 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } } - if (!pushed && inv.type == MSG_DSTX) { - if(mapDarksendBroadcastTxes.count(inv.hash)){ + if (!pushed && inv.type == MSG_DSTX) + { + if(mapDarksendBroadcastTxes.count(inv.hash)) + { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(1000); ss << @@ -4581,9 +4605,8 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } - if (!pushed) { + if (!pushed) vNotFound.push_back(inv); - } } // Track requests for our stuff. @@ -4613,6 +4636,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, const CChainParams& chainparams = Params(); RandAddSeedPerfmon(); LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id); + if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0) { LogPrintf("dropmessagestest DROPPING RECV MESSAGE\n"); @@ -4878,6 +4902,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, std::vector vToFetch; + for (unsigned int nInv = 0; nInv < vInv.size(); nInv++) { const CInv &inv = vInv[nInv]; @@ -4915,8 +4940,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, { if (fBlocksOnly) LogPrint("net", "transaction (%s) inv sent in violation of protocol peer=%d\n", inv.hash.ToString(), pfrom->id); - else if (!fAlreadyHave && !fImporting && !fReindex) + else if (!fAlreadyHave && !fImporting && !fReindex) + { pfrom->AskFor(inv); + } } // Track requests for our stuff @@ -5610,6 +5637,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, ProcessMessageInstantX(pfrom, strCommand, vRecv); ProcessSpork(pfrom, strCommand, vRecv); masternodeSync.ProcessMessage(pfrom, strCommand, vRecv); + governance.ProcessMessage(pfrom, strCommand, vRecv); } else { @@ -6091,7 +6119,9 @@ bool SendMessages(CNode* pto) pto->mapAskFor.erase(pto->mapAskFor.begin()); } if (!vGetData.empty()) + { pto->PushMessage(NetMsgType::GETDATA, vGetData); + } } return true; diff --git a/src/masternode-sync.cpp b/src/masternode-sync.cpp index fe0e74da816da..120b0c0508c41 100644 --- a/src/masternode-sync.cpp +++ b/src/masternode-sync.cpp @@ -105,6 +105,25 @@ bool CMasternodeSync::IsBudgetFinEmpty() return sumBudgetItemFin==0 && countBudgetItemFin>0; } +std::string CMasternodeSync::GetAssetName() +{ + switch(RequestedMasternodeAssets) + { + case(MASTERNODE_SYNC_INITIAL): + return "MASTERNODE_SYNC_INITIAL"; + case(MASTERNODE_SYNC_FAILED): // should never be used here actually, use Reset() instead + return "MASTERNODE_SYNC_FAILED"; + case(MASTERNODE_SYNC_SPORKS): + return "MASTERNODE_SYNC_SPORKS"; + case(MASTERNODE_SYNC_LIST): + return "MASTERNODE_SYNC_LIST"; + case(MASTERNODE_SYNC_MNW): + return "MASTERNODE_SYNC_MNW"; + case(MASTERNODE_SYNC_GOVERNANCE): + return "MASTERNODE_SYNC_GOVERNANCE"; + } +} + void CMasternodeSync::GetNextAsset() { switch(RequestedMasternodeAssets) @@ -124,9 +143,9 @@ void CMasternodeSync::GetNextAsset() break; case(MASTERNODE_SYNC_MNW): lastBudgetItem = GetTime(); - RequestedMasternodeAssets = MASTERNODE_SYNC_BUDGET; + RequestedMasternodeAssets = MASTERNODE_SYNC_GOVERNANCE; break; - case(MASTERNODE_SYNC_BUDGET): + case(MASTERNODE_SYNC_GOVERNANCE): LogPrintf("CMasternodeSync::GetNextAsset - Sync has finished\n"); RequestedMasternodeAssets = MASTERNODE_SYNC_FINISHED; uiInterface.NotifyAdditionalDataSyncProgressChanged(1); @@ -143,7 +162,7 @@ std::string CMasternodeSync::GetSyncStatus() case MASTERNODE_SYNC_SPORKS: return _("Synchronizing sporks..."); case MASTERNODE_SYNC_LIST: return _("Synchronizing masternodes..."); case MASTERNODE_SYNC_MNW: return _("Synchronizing masternode winners..."); - case MASTERNODE_SYNC_BUDGET: return _("Synchronizing budgets..."); + case MASTERNODE_SYNC_GOVERNANCE: return _("Synchronizing governance objects..."); case MASTERNODE_SYNC_FAILED: return _("Synchronization failed"); case MASTERNODE_SYNC_FINISHED: return _("Synchronization finished"); } @@ -172,13 +191,13 @@ void CMasternodeSync::ProcessMessage(CNode* pfrom, std::string& strCommand, CDat sumMasternodeWinner += nCount; countMasternodeWinner++; break; - case(MASTERNODE_SYNC_BUDGET_PROP): - if(RequestedMasternodeAssets != MASTERNODE_SYNC_BUDGET) return; + case(MASTERNODE_SYNC_GOVOBJ): + if(RequestedMasternodeAssets != MASTERNODE_SYNC_GOVERNANCE) return; sumBudgetItemProp += nCount; countBudgetItemProp++; break; - case(MASTERNODE_SYNC_BUDGET_FIN): - if(RequestedMasternodeAssets != MASTERNODE_SYNC_BUDGET) return; + case(MASTERNODE_SYNC_GOVERNANCE_FIN): + if(RequestedMasternodeAssets != MASTERNODE_SYNC_GOVERNANCE) return; sumBudgetItemFin += nCount; countBudgetItemFin++; break; @@ -206,14 +225,12 @@ void CMasternodeSync::Process() { static int tick = 0; if(tick++ % 6 != 0) return; - if(!pCurrentBlockIndex) return; //the actual count of masternodes we have currently int nMnCount = mnodeman.CountEnabled(); // RESET SYNCING INCASE OF FAILURE - { if(IsSynced()) { /* @@ -221,8 +238,10 @@ void CMasternodeSync::Process() */ if(nMnCount == 0) { Reset(); - } else - return; + } else { + //if syncing is complete and we have masternodes, return + return; + } } //try syncing again @@ -233,25 +252,27 @@ void CMasternodeSync::Process() } } - double nSyncProgress = double(RequestedMasternodeAttempt + (RequestedMasternodeAssets - 1) * 8) / (8*4); - LogPrintf("CMasternodeSync::Process() - tick %d RequestedMasternodeAttempt %d RequestedMasternodeAssets %d nSyncProgress %f\n", tick, RequestedMasternodeAttempt, RequestedMasternodeAssets, nSyncProgress); - uiInterface.NotifyAdditionalDataSyncProgressChanged(nSyncProgress); + // INITIAL SYNC SETUP / LOG REPORTING + { + double nSyncProgress = double(RequestedMasternodeAttempt + (RequestedMasternodeAssets - 1) * 8) / (8*4); + LogPrintf("CMasternodeSync::Process() - tick %d RequestedMasternodeAttempt %d RequestedMasternodeAssets %d nSyncProgress %f\n", tick, RequestedMasternodeAttempt, RequestedMasternodeAssets, nSyncProgress); + uiInterface.NotifyAdditionalDataSyncProgressChanged(nSyncProgress); - if(RequestedMasternodeAssets == MASTERNODE_SYNC_INITIAL) GetNextAsset(); + if(RequestedMasternodeAssets == MASTERNODE_SYNC_INITIAL) GetNextAsset(); - // sporks synced but blockchain is not, wait until we're almost at a recent block to continue - if(Params().NetworkIDString() != CBaseChainParams::REGTEST && - !IsBlockchainSynced() && RequestedMasternodeAssets > MASTERNODE_SYNC_SPORKS) return; + // sporks synced but blockchain is not, wait until we're almost at a recent block to continue + if(Params().NetworkIDString() != CBaseChainParams::REGTEST && + !IsBlockchainSynced() && RequestedMasternodeAssets > MASTERNODE_SYNC_SPORKS) return; - TRY_LOCK(cs_vNodes, lockRecv); - if(!lockRecv) return; + TRY_LOCK(cs_vNodes, lockRecv); + if(!lockRecv) return; + } BOOST_FOREACH(CNode* pnode, vNodes) { - /* - REGTEST QUICK MODE - */ - if(Params().NetworkIDString() == CBaseChainParams::REGTEST){ + // QUICK MODE (REGTEST ONLY!) + if(Params().NetworkIDString() == CBaseChainParams::REGTEST) + { if(RequestedMasternodeAttempt <= 2) { pnode->PushMessage(NetMsgType::GETSPORKS); //get current network sporks } else if(RequestedMasternodeAttempt < 4) { @@ -260,7 +281,7 @@ void CMasternodeSync::Process() int nMnCount = mnodeman.CountEnabled(); pnode->PushMessage(NetMsgType::MNWINNERSSYNC, nMnCount); //sync payees uint256 n = uint256(); - pnode->PushMessage(NetMsgType::MNGOVERNANCEVOTESYNC, n); //sync masternode votes + pnode->PushMessage(NetMsgType::MNGOVERNANCESYNC, n); //sync masternode votes } else { RequestedMasternodeAssets = MASTERNODE_SYNC_FINISHED; } @@ -268,28 +289,29 @@ void CMasternodeSync::Process() return; } - /* - NORMAL NETWORK MODE - TESTNET/MAINNET - */ - - // ALWAYS ASK FOR SPORKS AS WE SYNC (we skip this mode now) - if(!pnode->HasFulfilledRequest("spork-sync")) - { - pnode->FulfilledRequest("spork-sync"); - pnode->PushMessage(NetMsgType::GETSPORKS); //get current network sporks - } - - //we always ask for sporks, so just skip this - if(RequestedMasternodeAssets == MASTERNODE_SYNC_SPORKS){ - GetNextAsset(); - return; - } + // NORMAL NETWORK MODE - TESTNET/MAINNET + { + // SPORK : ALWAYS ASK FOR SPORKS AS WE SYNC (we skip this mode now) - if (pnode->nVersion >= mnpayments.GetMinMasternodePaymentsProto()) { + if(!pnode->HasFulfilledRequest("spork-sync")) + { + pnode->FulfilledRequest("spork-sync"); - // SYNC MASTERNODE LIST FROM OTHER CONNECTED CLIENTS + // get current network sporks + pnode->PushMessage(NetMsgType::GETSPORKS); + + // we always ask for sporks, so just skip this + if(RequestedMasternodeAssets == MASTERNODE_SYNC_SPORKS){ + GetNextAsset(); + return; + } + } + + // MNLIST : SYNC MASTERNODE LIST FROM OTHER CONNECTED CLIENTS - if(RequestedMasternodeAssets == MASTERNODE_SYNC_LIST) { + if(RequestedMasternodeAssets == MASTERNODE_SYNC_LIST) + { + if (pnode->nVersion < mnpayments.GetMinMasternodePaymentsProto()) continue; // shall we move onto the next asset? if(nMnCount > mnodeman.GetEstimatedMasternodes(pCurrentBlockIndex->nHeight)*0.9) @@ -317,9 +339,11 @@ void CMasternodeSync::Process() return; //this will cause each peer to get one request each six seconds for the various assets we need } - // SYNC MASTERNODE WINNERS FROM OTHER CONNECTED CLIENTS + // MNW : SYNC MASTERNODE WINNERS FROM OTHER CONNECTED CLIENTS - if(RequestedMasternodeAssets == MASTERNODE_SYNC_MNW) { + if(RequestedMasternodeAssets == MASTERNODE_SYNC_MNW) + { + if (pnode->nVersion < mnpayments.GetMinMasternodePaymentsProto()) continue; // Shall we move onto the next asset? // -- @@ -346,11 +370,13 @@ void CMasternodeSync::Process() return; //this will cause each peer to get one request each six seconds for the various assets we need } - } + + // GOVOBJ : SYNC GOVERNANCE ITEMS FROM OUR PEERS + + if(RequestedMasternodeAssets == MASTERNODE_SYNC_GOVERNANCE){ + if (pnode->nVersion < MSG_GOVERNANCE_PEER_PROTO_VERSION) continue; + - if (pnode->nVersion >= MIN_BUDGET_PEER_PROTO_VERSION) { - // MODE : MASTERNODE_SYNC_BUDGET - if(RequestedMasternodeAssets == MASTERNODE_SYNC_BUDGET){ // shall we move onto the next asset // if(countBudgetItemProp > 0 && countBudgetItemFin) // { @@ -364,14 +390,14 @@ void CMasternodeSync::Process() // } // } - //we'll start rejecting votes if we accidentally get set as synced too soon, this allows plenty of time - if(lastBudgetItem < GetTime() - MASTERNODE_SYNC_TIMEOUT){ - GetNextAsset(); + // //we'll start rejecting votes if we accidentally get set as synced too soon, this allows plenty of time + // if(lastBudgetItem < GetTime() - MASTERNODE_SYNC_TIMEOUT){ + // GetNextAsset(); - //try to activate our masternode if possible - activeMasternode.ManageStatus(); - return; - } + // //try to activate our masternode if possible + // activeMasternode.ManageStatus(); + // return; + // } // requesting is the last thing we do, incase we needed to move to the next asset and we've requested from each peer already @@ -379,12 +405,11 @@ void CMasternodeSync::Process() pnode->FulfilledRequest("governance-sync"); uint256 n = uint256(); - pnode->PushMessage(NetMsgType::MNGOVERNANCEVOTESYNC, n); //sync masternode votes + pnode->PushMessage(NetMsgType::MNGOVERNANCESYNC, n); //sync masternode votes RequestedMasternodeAttempt++; return; //this will cause each peer to get one request each six seconds for the various assets we need } - } } } diff --git a/src/masternode-sync.h b/src/masternode-sync.h index 41ae8ebcd3a2a..9cda693d5680f 100644 --- a/src/masternode-sync.h +++ b/src/masternode-sync.h @@ -9,9 +9,9 @@ #define MASTERNODE_SYNC_SPORKS 1 #define MASTERNODE_SYNC_LIST 2 #define MASTERNODE_SYNC_MNW 3 -#define MASTERNODE_SYNC_BUDGET 4 -#define MASTERNODE_SYNC_BUDGET_PROP 10 -#define MASTERNODE_SYNC_BUDGET_FIN 11 +#define MASTERNODE_SYNC_GOVERNANCE 4 +#define MASTERNODE_SYNC_GOVOBJ 10 +#define MASTERNODE_SYNC_GOVERNANCE_FIN 11 #define MASTERNODE_SYNC_FAILED 998 #define MASTERNODE_SYNC_FINISHED 999 @@ -64,6 +64,7 @@ class CMasternodeSync void AddedMasternodeWinner(uint256 hash); void AddedBudgetItem(uint256 hash); void GetNextAsset(); + std::string GetAssetName(); std::string GetSyncStatus(); void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv); bool IsBudgetFinEmpty(); diff --git a/src/net.cpp b/src/net.cpp index 2ce6b1fe18036..1f212b4c5e08c 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2464,6 +2464,7 @@ void CNode::AskFor(const CInv& inv) nRequestTime = it->second; else nRequestTime = 0; + LogPrint("net", "askfor %s %d (%s) peer=%d\n", inv.ToString(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000), id); // Make sure not to reuse time indexes to keep things in the same order diff --git a/src/protocol.cpp b/src/protocol.cpp index 1b7f6dc5e0895..26888036aa126 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -43,9 +43,9 @@ const char *GETSPORKS="getsporks"; const char *MNWINNER="mnw"; const char *MNWINNERSSYNC="mnget"; const char *MNSCANERROR="mn scan error"; // not implemented -const char *MNGOVERNANCEVOTESYNC="mnvs"; +const char *MNGOVERNANCESYNC="mnvs"; const char *MNGOVERNANCEVOTE="mvote"; -const char *MNGOVERNANCEPROPOSAL="mprop"; +const char *MNGOVERNANCEOBJECT="mprop"; const char *MNGOVERNANCEFINAL="fbs"; const char *MNGOVERNANCEFINALVOTE="fbvote"; const char *MNQUORUM="mn quorum"; // not implemented @@ -76,7 +76,7 @@ static const char* ppszTypeName[] = NetMsgType::MNWINNER, NetMsgType::MNSCANERROR, // not implemented NetMsgType::MNGOVERNANCEVOTE, - NetMsgType::MNGOVERNANCEPROPOSAL, + NetMsgType::MNGOVERNANCEOBJECT, NetMsgType::MNGOVERNANCEFINAL, NetMsgType::MNGOVERNANCEFINALVOTE, NetMsgType::MNQUORUM, // not implemented @@ -118,9 +118,9 @@ const static std::string allNetMessageTypes[] = { NetMsgType::GETSPORKS, NetMsgType::MNWINNER, NetMsgType::MNWINNERSSYNC, - NetMsgType::MNGOVERNANCEVOTESYNC, + NetMsgType::MNGOVERNANCESYNC, NetMsgType::MNGOVERNANCEVOTE, - NetMsgType::MNGOVERNANCEPROPOSAL, + NetMsgType::MNGOVERNANCEOBJECT, NetMsgType::MNGOVERNANCEFINAL, NetMsgType::MNGOVERNANCEFINALVOTE, NetMsgType::MNANNOUNCE, diff --git a/src/protocol.h b/src/protocol.h index 81809d88ecbf5..cdd7f0639af31 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -227,9 +227,9 @@ extern const char *SPORK; extern const char *GETSPORKS; extern const char *MNWINNER; extern const char *MNWINNERSSYNC; -extern const char *MNGOVERNANCEVOTESYNC; +extern const char *MNGOVERNANCESYNC; extern const char *MNGOVERNANCEVOTE; -extern const char *MNGOVERNANCEPROPOSAL; +extern const char *MNGOVERNANCEOBJECT; extern const char *MNGOVERNANCEFINAL; extern const char *MNGOVERNANCEFINALVOTE; extern const char *MNANNOUNCE; @@ -346,8 +346,8 @@ enum { MSG_SPORK, MSG_MASTERNODE_WINNER, MSG_MASTERNODE_SCANNING_ERROR, // not implemented - MSG_BUDGET_VOTE, - MSG_BUDGET_PROPOSAL, + MSG_GOVERNANCE_VOTE, + MSG_GOVERNANCE_OBJECT, MSG_BUDGET_FINALIZED, MSG_BUDGET_FINALIZED_VOTE, MSG_MASTERNODE_QUORUM, // not implemented diff --git a/src/rpcmasternode-budget.cpp b/src/rpcmasternode-budget.cpp index f74609a3b6488..2eaefad21af32 100644 --- a/src/rpcmasternode-budget.cpp +++ b/src/rpcmasternode-budget.cpp @@ -79,8 +79,6 @@ UniValue mngovernance(const UniValue& params, bool fHelp) /* - - 12.1 todo - @@ -91,8 +89,6 @@ UniValue mngovernance(const UniValue& params, bool fHelp) Command: mngovernance submit 6e622bb41bad1fb18e7f23ae96770aeb33129e18bd9efe790522488e580a0a03 0 1 1464292854 "beer-reimbursement" 5b5b22636f6e7472616374222c207b2270726f6a6563745f6e616d65223a20225c22626565722d7265696d62757273656d656e745c22222c20227061796d656e745f61646472657373223a20225c225879324c4b4a4a64655178657948726e34744744514238626a6876464564615576375c22222c2022656e645f64617465223a202231343936333030343030222c20226465736372697074696f6e5f75726c223a20225c227777772e646173687768616c652e6f72672f702f626565722d7265696d62757273656d656e745c22222c2022636f6e74726163745f75726c223a20225c22626565722d7265696d62757273656d656e742e636f6d2f3030312e7064665c22222c20227061796d656e745f616d6f756e74223a20223233342e323334323232222c2022676f7665726e616e63655f6f626a6563745f6964223a2037342c202273746172745f64617465223a202231343833323534303030227d5d5d1 - - */ if(strCommand == "prepare") @@ -265,7 +261,6 @@ UniValue mngovernance(const UniValue& params, bool fHelp) continue; } - std::string strError = ""; if(governance.UpdateGovernanceObject(vote, NULL, strError)) { governance.mapSeenVotes.insert(make_pair(vote.GetHash(), SEEN_OBJECT_IS_VALID)); diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 743db89eeb30e..0c4e4c8f2fabe 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -142,8 +142,8 @@ UniValue mnsync(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error( - "mnsync [status|reset]\n" - "Returns the sync status or resets sync.\n" + "mnsync [status|next|reset]\n" + "Returns the sync status, updates to the next step or resets it entirely.\n" ); std::string strMode = params[0].get_str(); @@ -172,6 +172,12 @@ UniValue mnsync(const UniValue& params, bool fHelp) return obj; } + if(strMode == "next") + { + masternodeSync.GetNextAsset(); + return "sync updated to " + masternodeSync.GetAssetName(); + } + if(strMode == "reset") { masternodeSync.Reset(); diff --git a/src/version.h b/src/version.h index 99cfee0d826c1..f824c00497a11 100644 --- a/src/version.h +++ b/src/version.h @@ -19,13 +19,13 @@ static const int INIT_PROTO_VERSION = 209; static const int GETHEADERS_VERSION = 70077; //! disconnect from peers older than this proto version -static const int MIN_PEER_PROTO_VERSION = 70066; +static const int MIN_PEER_PROTO_VERSION = 70103; //! minimum peer version accepted by DarksendPool -static const int MIN_POOL_PEER_PROTO_VERSION = 70103; +static const int MIN_POOL_PEER_PROTO_VERSION = 70200; //! minimum peer version for masternode budgets -static const int MIN_BUDGET_PEER_PROTO_VERSION = 70103; +static const int MSG_GOVERNANCE_PEER_PROTO_VERSION = 70200; //! minimum peer version for masternode winner broadcasts static const int MIN_MNW_PEER_PROTO_VERSION = 70103; @@ -33,8 +33,8 @@ static const int MIN_MNW_PEER_PROTO_VERSION = 70103; //! minimum peer version that can receive masternode payments // V1 - Last protocol version before update // V2 - Newest protocol version -static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_1 = 70066; -static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_2 = 70103; +static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_1 = 70103; +static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_2 = 70200; //! nTime field added to CAddress, starting with this version; //! if possible, avoid requesting addresses nodes older than this From 15821fe2d4826a0a2c3ccb9fcb8ae94f396c98c4 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Mon, 6 Jun 2016 16:06:52 -0700 Subject: [PATCH 2/9] - Added const where possible - Uncommented sync block - Protocol min 70201 - Fixed bug which flags invalid votes incorrectly - Formatting --- src/governance-vote.h | 5 +++-- src/governance.cpp | 42 +++++++++++++++++++++++++---------------- src/governance.h | 8 ++++---- src/masternode-sync.cpp | 14 +++++++------- src/masternode-sync.h | 6 +++--- src/rpcmisc.cpp | 1 + src/version.h | 6 +++--- 7 files changed, 47 insertions(+), 35 deletions(-) diff --git a/src/governance-vote.h b/src/governance-vote.h index 36b9eed633f10..e8376d96f237a 100644 --- a/src/governance-vote.h +++ b/src/governance-vote.h @@ -76,7 +76,8 @@ class CGovernanceVote return ret; } - uint256 GetHash(){ + uint256 GetHash() const + { CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); ss << vinMasternode; ss << nParentHash; @@ -87,7 +88,7 @@ class CGovernanceVote } // GET HASH WITH DETERMINISTIC HASH OF PARENT-HASH/VOTE-TYPE - uint256 GetTypeHash() + uint256 GetTypeHash() const { // CALCULATE HOW TO STORE VOTE IN governance.mapVotes diff --git a/src/governance.cpp b/src/governance.cpp index 0f0572ffc4ed3..46b318ebbaa77 100644 --- a/src/governance.cpp +++ b/src/governance.cpp @@ -106,8 +106,9 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C LOCK(cs_budget); // GOVERANCE SYNCING FUNCTIONALITY + if (strCommand == NetMsgType::MNGOVERNANCESYNC) + { - if (strCommand == NetMsgType::MNGOVERNANCESYNC) { uint256 nProp; vRecv >> nProp; @@ -125,11 +126,14 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C // ask for a specific proposal and it's votes Sync(pfrom, nProp); LogPrint("mngovernance", "syncing governance objects to our peer at %s\n", pfrom->addr.ToString()); + } // NEW GOVERNANCE OBJECT + else if (strCommand == NetMsgType::MNGOVERNANCEOBJECT) + + { - if (strCommand == NetMsgType::MNGOVERNANCEOBJECT) { CGovernanceObject govobj; vRecv >> govobj; @@ -165,11 +169,14 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C LogPrintf("Governance object - new! - %s\n", govobj.GetHash().ToString()); //We might have active votes for this proposal that are valid now CheckOrphanVotes(); + } // NEW GOVERNANCE OBJECT VOTE + else if (strCommand == NetMsgType::MNGOVERNANCEVOTE) + + { - if (strCommand == NetMsgType::MNGOVERNANCEVOTE) { CGovernanceVote vote; vRecv >> vote; vote.fValid = true; @@ -186,13 +193,15 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C return; } - mapSeenVotes.insert(make_pair(vote.GetHash(), SEEN_OBJECT_IS_VALID)); if(!vote.IsValid(true)){ LogPrintf("mngovernance - signature invalid\n"); if(masternodeSync.IsSynced()) Misbehaving(pfrom->GetId(), 20); // it could just be a non-synced masternode mnodeman.AskForMN(pfrom, vote.vinMasternode); + mapSeenVotes.insert(make_pair(vote.GetHash(), SEEN_OBJECT_ERROR_INVALID)); return; + } else { + mapSeenVotes.insert(make_pair(vote.GetHash(), SEEN_OBJECT_IS_VALID)); } std::string strError = ""; @@ -299,7 +308,7 @@ CGovernanceObject *CGovernanceManager::FindGovernanceObject(const std::string &s return pGovObj; } -CGovernanceObject *CGovernanceManager::FindGovernanceObject(uint256& nHash) +CGovernanceObject *CGovernanceManager::FindGovernanceObject(const uint256& nHash) { LOCK(cs); @@ -469,7 +478,7 @@ void CGovernanceManager::Sync(CNode* pfrom, uint256 nProp) LogPrintf("CGovernanceManager::Sync - sent %d items\n", nInvCount); } -void CGovernanceManager::SyncParentObjectByVote(CNode* pfrom, CGovernanceVote& vote) +void CGovernanceManager::SyncParentObjectByVote(CNode* pfrom, const CGovernanceVote& vote) { if(!mapAskedForGovernanceObject.count(vote.nParentHash)){ pfrom->PushMessage(NetMsgType::MNGOVERNANCESYNC, vote.nParentHash); @@ -477,7 +486,7 @@ void CGovernanceManager::SyncParentObjectByVote(CNode* pfrom, CGovernanceVote& v } } -bool CGovernanceManager::UpdateGovernanceObject(CGovernanceVote& vote, CNode* pfrom, std::string& strError) +bool CGovernanceManager::UpdateGovernanceObject(const CGovernanceVote& vote, CNode* pfrom, std::string& strError) { LOCK(cs); @@ -501,29 +510,30 @@ bool CGovernanceManager::UpdateGovernanceObject(CGovernanceVote& vote, CNode* pf return AddOrUpdateVote(vote, strError); } -bool CGovernanceManager::AddOrUpdateVote(CGovernanceVote& vote, std::string& strError) +bool CGovernanceManager::AddOrUpdateVote(const CGovernanceVote& vote, std::string& strError) { LOCK(cs); // GET DETERMINISTIC HASH INCLUDING PARENT/TYPE - uint256 hash = vote.GetTypeHash(); + uint256 nTypeHash = vote.GetTypeHash(); + uint256 nHash = vote.GetHash(); - if(mapVotesByType.count(hash)) + if(mapVotesByType.count(nTypeHash)) { - if(mapVotesByType[hash].nTime > vote.nTime){ - strError = strprintf("new vote older than existing vote - %s", vote.GetHash().ToString()); + if(mapVotesByType[nTypeHash].nTime > vote.nTime){ + strError = strprintf("new vote older than existing vote - %s", nTypeHash.ToString()); LogPrint("mngovernance", "CGovernanceObject::AddOrUpdateVote - %s\n", strError); return false; } - if(vote.nTime - mapVotesByType[hash].nTime < GOVERNANCE_UPDATE_MIN){ - strError = strprintf("time between votes is too soon - %s - %lli", vote.GetHash().ToString(), vote.nTime - mapVotesByType[hash].nTime); + if(vote.nTime - mapVotesByType[nTypeHash].nTime < GOVERNANCE_UPDATE_MIN){ + strError = strprintf("time between votes is too soon - %s - %lli", nTypeHash.ToString(), vote.nTime - mapVotesByType[nHash].nTime); LogPrint("mngovernance", "CGovernanceObject::AddOrUpdateVote - %s\n", strError); return false; } } - mapVotesByType[vote.GetTypeHash()] = vote; - mapVotesByHash[vote.GetHash()] = vote; + mapVotesByType[nTypeHash] = vote; + mapVotesByHash[nHash] = vote; return true; } diff --git a/src/governance.h b/src/governance.h index 8f6564bd4725c..fb1959518f493 100644 --- a/src/governance.h +++ b/src/governance.h @@ -98,13 +98,13 @@ class CGovernanceManager //void ResetSync(); //void MarkSynced(); void Sync(CNode* node, uint256 nProp); - void SyncParentObjectByVote(CNode* pfrom, CGovernanceVote& vote); + void SyncParentObjectByVote(CNode* pfrom, const CGovernanceVote& vote); void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv); void NewBlock(); CGovernanceObject *FindGovernanceObject(const std::string &strName); - CGovernanceObject *FindGovernanceObject(uint256& nHash); + CGovernanceObject *FindGovernanceObject(const uint256& nHash); std::vector GetAllProposals(int64_t nMoreThanTime); @@ -112,8 +112,8 @@ class CGovernanceManager bool IsBudgetPaymentBlock(int nBlockHeight); bool AddGovernanceObject (CGovernanceObject& govobj); - bool UpdateGovernanceObject(CGovernanceVote& vote, CNode* pfrom, std::string& strError); - bool AddOrUpdateVote(CGovernanceVote& vote, std::string& strError); + bool UpdateGovernanceObject(const CGovernanceVote& vote, CNode* pfrom, std::string& strError); + bool AddOrUpdateVote(const CGovernanceVote& vote, std::string& strError); std::string GetRequiredPaymentsString(int nBlockHeight); void CleanAndRemove(bool fSignatureCheck); void CheckAndRemove(); diff --git a/src/masternode-sync.cpp b/src/masternode-sync.cpp index 120b0c0508c41..08b765e62a770 100644 --- a/src/masternode-sync.cpp +++ b/src/masternode-sync.cpp @@ -390,14 +390,14 @@ void CMasternodeSync::Process() // } // } - // //we'll start rejecting votes if we accidentally get set as synced too soon, this allows plenty of time - // if(lastBudgetItem < GetTime() - MASTERNODE_SYNC_TIMEOUT){ - // GetNextAsset(); + //we'll start rejecting votes if we accidentally get set as synced too soon, this allows plenty of time + if(lastBudgetItem < GetTime() - MASTERNODE_SYNC_TIMEOUT){ + GetNextAsset(); - // //try to activate our masternode if possible - // activeMasternode.ManageStatus(); - // return; - // } + //try to activate our masternode if possible + activeMasternode.ManageStatus(); + return; + } // requesting is the last thing we do, incase we needed to move to the next asset and we've requested from each peer already diff --git a/src/masternode-sync.h b/src/masternode-sync.h index 9cda693d5680f..3c3bf0b422197 100644 --- a/src/masternode-sync.h +++ b/src/masternode-sync.h @@ -9,9 +9,9 @@ #define MASTERNODE_SYNC_SPORKS 1 #define MASTERNODE_SYNC_LIST 2 #define MASTERNODE_SYNC_MNW 3 -#define MASTERNODE_SYNC_GOVERNANCE 4 -#define MASTERNODE_SYNC_GOVOBJ 10 -#define MASTERNODE_SYNC_GOVERNANCE_FIN 11 +#define MASTERNODE_SYNC_GOVERNANCE 4 +#define MASTERNODE_SYNC_GOVOBJ 10 +#define MASTERNODE_SYNC_GOVERNANCE_FIN 11 #define MASTERNODE_SYNC_FAILED 998 #define MASTERNODE_SYNC_FINISHED 999 diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 0c4e4c8f2fabe..35fbd147a1056 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -152,6 +152,7 @@ UniValue mnsync(const UniValue& params, bool fHelp) UniValue obj(UniValue::VOBJ); obj.push_back(Pair("IsBlockchainSynced", masternodeSync.IsBlockchainSynced())); + obj.push_back(Pair("CurrentSyncingAssetName", masternodeSync.GetAssetName())); obj.push_back(Pair("lastMasternodeList", masternodeSync.lastMasternodeList)); obj.push_back(Pair("lastMasternodeWinner", masternodeSync.lastMasternodeWinner)); obj.push_back(Pair("lastBudgetItem", masternodeSync.lastBudgetItem)); diff --git a/src/version.h b/src/version.h index f824c00497a11..56751feeb7279 100644 --- a/src/version.h +++ b/src/version.h @@ -22,10 +22,10 @@ static const int GETHEADERS_VERSION = 70077; static const int MIN_PEER_PROTO_VERSION = 70103; //! minimum peer version accepted by DarksendPool -static const int MIN_POOL_PEER_PROTO_VERSION = 70200; +static const int MIN_POOL_PEER_PROTO_VERSION = 70201; //! minimum peer version for masternode budgets -static const int MSG_GOVERNANCE_PEER_PROTO_VERSION = 70200; +static const int MSG_GOVERNANCE_PEER_PROTO_VERSION = 70201; //! minimum peer version for masternode winner broadcasts static const int MIN_MNW_PEER_PROTO_VERSION = 70103; @@ -34,7 +34,7 @@ static const int MIN_MNW_PEER_PROTO_VERSION = 70103; // V1 - Last protocol version before update // V2 - Newest protocol version static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_1 = 70103; -static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_2 = 70200; +static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_2 = 70201; //! nTime field added to CAddress, starting with this version; //! if possible, avoid requesting addresses nodes older than this From aa8fdd76aac664d528a957c148ed575aa444c382 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Mon, 6 Jun 2016 16:55:16 -0700 Subject: [PATCH 3/9] fix curly braces --- src/governance.cpp | 9 +++---- src/main.cpp | 59 +++++++++++++++------------------------------- 2 files changed, 22 insertions(+), 46 deletions(-) diff --git a/src/governance.cpp b/src/governance.cpp index 46b318ebbaa77..5a10446e447bd 100644 --- a/src/governance.cpp +++ b/src/governance.cpp @@ -452,8 +452,7 @@ void CGovernanceManager::Sync(CNode* pfrom, uint256 nProp) // SYNC GOVERNANCE OBJECTS WITH OTHER CLIENT std::map::iterator it1 = mapObjects.begin(); - while(it1 != mapObjects.end()) - { + while(it1 != mapObjects.end()) { uint256 h = (*it1).first; if((*it1).second.fCachedValid && ((nProp == uint256() || (h == nProp)))){ @@ -467,8 +466,7 @@ void CGovernanceManager::Sync(CNode* pfrom, uint256 nProp) // SYNC OUR GOVERNANCE OBJECT VOTES WITH THEIR GOVERNANCE OBJECT VOTES std::map::iterator it2 = mapVotesByHash.begin(); - while(it2 != mapVotesByHash.end()) - { + while(it2 != mapVotesByHash.end()) { pfrom->PushInventory(CInv(MSG_GOVERNANCE_VOTE, (*it2).first)); nInvCount++; ++it2; @@ -518,8 +516,7 @@ bool CGovernanceManager::AddOrUpdateVote(const CGovernanceVote& vote, std::strin uint256 nTypeHash = vote.GetTypeHash(); uint256 nHash = vote.GetHash(); - if(mapVotesByType.count(nTypeHash)) - { + if(mapVotesByType.count(nTypeHash)) { if(mapVotesByType[nTypeHash].nTime > vote.nTime){ strError = strprintf("new vote older than existing vote - %s", nTypeHash.ToString()); LogPrint("mngovernance", "CGovernanceObject::AddOrUpdateVote - %s\n", strError); diff --git a/src/main.cpp b/src/main.cpp index b2a77bc4ab0ad..ec4f66526774e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4425,8 +4425,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } // Pruned nodes may have deleted the block, so check whether // it's available before trying to send. - if (send && (mi->second->nStatus & BLOCK_HAVE_DATA)) - { + if (send && (mi->second->nStatus & BLOCK_HAVE_DATA)) { // Send block from disk CBlock block; if (!ReadBlockFromDisk(block, (*mi).second, consensusParams)) @@ -4480,11 +4479,9 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } } - if (!pushed && inv.type == MSG_TX) - { + if (!pushed && inv.type == MSG_TX) { CTransaction tx; - if (mempool.lookup(inv.hash, tx)) - { + if (mempool.lookup(inv.hash, tx)) { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(1000); ss << tx; @@ -4493,10 +4490,8 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } } - if (!pushed && inv.type == MSG_TXLOCK_VOTE) - { - if(mapTxLockVote.count(inv.hash)) - { + if (!pushed && inv.type == MSG_TXLOCK_VOTE) { + if(mapTxLockVote.count(inv.hash)) { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(1000); ss << mapTxLockVote[inv.hash]; @@ -4505,10 +4500,8 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } } - if (!pushed && inv.type == MSG_TXLOCK_REQUEST) - { - if(mapTxLockReq.count(inv.hash)) - { + if (!pushed && inv.type == MSG_TXLOCK_REQUEST) { + if(mapTxLockReq.count(inv.hash)) { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(1000); ss << mapTxLockReq[inv.hash]; @@ -4517,10 +4510,8 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } } - if (!pushed && inv.type == MSG_SPORK) - { - if(mapSporks.count(inv.hash)) - { + if (!pushed && inv.type == MSG_SPORK) { + if(mapSporks.count(inv.hash)) { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(1000); ss << mapSporks[inv.hash]; @@ -4529,10 +4520,8 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } } - if (!pushed && inv.type == MSG_MASTERNODE_WINNER) - { - if(mnpayments.mapMasternodePayeeVotes.count(inv.hash)) - { + if (!pushed && inv.type == MSG_MASTERNODE_WINNER) { + if(mnpayments.mapMasternodePayeeVotes.count(inv.hash)) { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(1000); ss << mnpayments.mapMasternodePayeeVotes[inv.hash]; @@ -4541,10 +4530,8 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } } - if (!pushed && inv.type == MSG_GOVERNANCE_VOTE) - { - if(governance.mapVotesByHash.count(inv.hash)) - { + if (!pushed && inv.type == MSG_GOVERNANCE_VOTE) { + if(governance.mapVotesByHash.count(inv.hash)) { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(1000); ss << governance.mapVotesByHash[inv.hash]; @@ -4553,10 +4540,8 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } } - if (!pushed && inv.type == MSG_GOVERNANCE_OBJECT) - { - if(governance.mapObjects.count(inv.hash)) - { + if (!pushed && inv.type == MSG_GOVERNANCE_OBJECT) { + if(governance.mapObjects.count(inv.hash)) { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(1000); ss << governance.mapObjects[inv.hash]; @@ -4575,10 +4560,8 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } } - if (!pushed && inv.type == MSG_MASTERNODE_PING) - { - if(mnodeman.mapSeenMasternodePing.count(inv.hash)) - { + if (!pushed && inv.type == MSG_MASTERNODE_PING) { + if(mnodeman.mapSeenMasternodePing.count(inv.hash)) { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(1000); ss << mnodeman.mapSeenMasternodePing[inv.hash]; @@ -4587,10 +4570,8 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } } - if (!pushed && inv.type == MSG_DSTX) - { - if(mapDarksendBroadcastTxes.count(inv.hash)) - { + if (!pushed && inv.type == MSG_DSTX) { + if(mapDarksendBroadcastTxes.count(inv.hash)) { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(1000); ss << @@ -6119,9 +6100,7 @@ bool SendMessages(CNode* pto) pto->mapAskFor.erase(pto->mapAskFor.begin()); } if (!vGetData.empty()) - { pto->PushMessage(NetMsgType::GETDATA, vGetData); - } } return true; From d8e39b1cde922460f5d2565c59051bd50e81f004 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Tue, 7 Jun 2016 06:50:55 -0700 Subject: [PATCH 4/9] Fix GetTypeHash bug - Should not collide based on the outcome --- src/governance-vote.h | 24 ++++++++++++++++++++++-- src/governance.cpp | 7 ++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/governance-vote.h b/src/governance-vote.h index e8376d96f237a..ae57368c55b21 100644 --- a/src/governance-vote.h +++ b/src/governance-vote.h @@ -76,6 +76,12 @@ class CGovernanceVote return ret; } + /** + * GetHash() + * + * GET UNIQUE HASH WITH DETERMINISTIC VALUE OF THIS SPECIFIC VOTE + */ + uint256 GetHash() const { CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); @@ -87,7 +93,21 @@ class CGovernanceVote return ss.GetHash(); } - // GET HASH WITH DETERMINISTIC HASH OF PARENT-HASH/VOTE-TYPE + /** + * GetTypeHash() + * + * GET HASH WITH DETERMINISTIC VALUE OF MASTERNODE-VIN/PARENT-HASH/VOTE-SIGNAL + * + * This hash collides with previous masternode votes when they update their votes on governance objects. + * With 12.1 there's various types of votes (funding, valid, delete, etc), so this is the deterministic hash + * that will collide with the previous vote and allow the system to update. + * + * -- + * + * We do not include an outcome, because that can change when a masternode updates their vote from yes to no + * on funding a specific project for example. + * We do not include a time because it will be updated each time the vote is updated, changing the hash + */ uint256 GetTypeHash() const { // CALCULATE HOW TO STORE VOTE IN governance.mapVotes @@ -96,7 +116,7 @@ class CGovernanceVote ss << vinMasternode; ss << nParentHash; ss << nVoteSignal; - ss << nVoteOutcome; + // -- no outcome // -- timeless return ss.GetHash(); } diff --git a/src/governance.cpp b/src/governance.cpp index 5a10446e447bd..f804767fec8d6 100644 --- a/src/governance.cpp +++ b/src/governance.cpp @@ -512,10 +512,13 @@ bool CGovernanceManager::AddOrUpdateVote(const CGovernanceVote& vote, std::strin { LOCK(cs); - // GET DETERMINISTIC HASH INCLUDING PARENT/TYPE + // GET DETERMINISTIC HASH WHICH COLLIDES ON MASTERNODE-VIN/GOVOBJ-HASH/VOTE-SIGNAL + uint256 nTypeHash = vote.GetTypeHash(); uint256 nHash = vote.GetHash(); + // LOOK FOR PREVIOUS VOTES BY THIS SPECIFIC MASTERNODE FOR THIS SPECIFIC SIGNAL + if(mapVotesByType.count(nTypeHash)) { if(mapVotesByType[nTypeHash].nTime > vote.nTime){ strError = strprintf("new vote older than existing vote - %s", nTypeHash.ToString()); @@ -529,6 +532,8 @@ bool CGovernanceManager::AddOrUpdateVote(const CGovernanceVote& vote, std::strin } } + // UPDATE TO NEWEST VOTE + mapVotesByType[nTypeHash] = vote; mapVotesByHash[nHash] = vote; return true; From 732a8a3cf0b6a004f453ef7ab0cee6178aa0d1c3 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Tue, 7 Jun 2016 16:16:07 -0700 Subject: [PATCH 5/9] fixed mismatched index for vote map --- src/governance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/governance.cpp b/src/governance.cpp index f804767fec8d6..201687459be76 100644 --- a/src/governance.cpp +++ b/src/governance.cpp @@ -526,7 +526,7 @@ bool CGovernanceManager::AddOrUpdateVote(const CGovernanceVote& vote, std::strin return false; } if(vote.nTime - mapVotesByType[nTypeHash].nTime < GOVERNANCE_UPDATE_MIN){ - strError = strprintf("time between votes is too soon - %s - %lli", nTypeHash.ToString(), vote.nTime - mapVotesByType[nHash].nTime); + strError = strprintf("time between votes is too soon - %s - %lli", nTypeHash.ToString(), vote.nTime - mapVotesByType[nTypeHash].nTime); LogPrint("mngovernance", "CGovernanceObject::AddOrUpdateVote - %s\n", strError); return false; } From 98b7d29f0294508efb2836385ab2725e11db1c10 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Thu, 9 Jun 2016 10:22:25 -0700 Subject: [PATCH 6/9] fix invalid cached govobj values --- src/governance.cpp | 24 ++++++++++++++++++++++-- src/governance.h | 2 ++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/governance.cpp b/src/governance.cpp index 201687459be76..11356a1ecb5b1 100644 --- a/src/governance.cpp +++ b/src/governance.cpp @@ -133,6 +133,9 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C else if (strCommand == NetMsgType::MNGOVERNANCEOBJECT) { + // MAKE SURE WE HAVE A VALID REFERENCE TO THE TIP BEFORE CONTINUING + + if(!pCurrentBlockIndex) return; CGovernanceObject govobj; vRecv >> govobj; @@ -157,7 +160,10 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C LogPrintf("Governance object is invalid - %s\n", strError); return; } + + // UPDATE CACHED VARIABLES FOR THIS OBJECT AND ADD IT TO OUR MANANGED DATA + govobj.UpdateSentinelVariables(pCurrentBlockIndex); if(AddGovernanceObject(govobj)) { govobj.Relay(); @@ -254,6 +260,10 @@ void CGovernanceManager::CheckAndRemove() { LogPrintf("CGovernanceManager::CheckAndRemove \n"); + // DOUBLE CHECK THAT WE HAVE A VALID POINTER TO TIP + + if(!pCurrentBlockIndex) return; + // DELETE OBJECTS WHICH MASTERNODE HAS FLAGGED DELETE=TRUE std::map::iterator it = mapObjects.begin(); @@ -268,8 +278,6 @@ void CGovernanceManager::CheckAndRemove() // UPDATE CACHING MECHANISMS FOR GOVERNANCE OBJECTS - if(!pCurrentBlockIndex) return; - std::string strError = ""; std::map::iterator it2 = mapObjects.begin(); @@ -563,6 +571,12 @@ CGovernanceObject::CGovernanceObject(uint256 nHashParentIn, int nRevisionIn, std strName = strNameIn; nTime = nTimeIn; nFeeTXHash = nFeeTXHashIn; //fee-tx + + // caching + fCachedFunding = false; + fCachedValid = true; + fCachedDelete = false; + fCachedEndorsed = false; } CGovernanceObject::CGovernanceObject(const CGovernanceObject& other) @@ -575,6 +589,12 @@ CGovernanceObject::CGovernanceObject(const CGovernanceObject& other) nTime = other.nTime; nFeeTXHash = other.nFeeTXHash; strData = other.strData; + + // caching + fCachedFunding = other.fCachedFunding; + fCachedValid = other.fCachedValid; + fCachedDelete = other.fCachedDelete; + fCachedEndorsed = other.fCachedEndorsed; } bool CGovernanceObject::IsValid(const CBlockIndex* pindex, std::string& strError, bool fCheckCollateral) diff --git a/src/governance.h b/src/governance.h index fb1959518f493..d79a957d420e7 100644 --- a/src/governance.h +++ b/src/governance.h @@ -310,6 +310,8 @@ class CGovernanceObject READWRITE(nTime); READWRITE(nFeeTXHash); READWRITE(strData); + + // AFTER DESERIALIZATION OCCURS, CACHED VARIABLES MUST BE CALCULATED MANUALLY } }; From 581b46a64c791f05ea0934d019f4baea25c71905 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Thu, 9 Jun 2016 10:34:33 -0700 Subject: [PATCH 7/9] added information explaining cached variable meanings --- src/governance.cpp | 5 +---- src/governance.h | 10 +++++----- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/governance.cpp b/src/governance.cpp index 11356a1ecb5b1..cf13d98fb31cd 100644 --- a/src/governance.cpp +++ b/src/governance.cpp @@ -164,10 +164,7 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C // UPDATE CACHED VARIABLES FOR THIS OBJECT AND ADD IT TO OUR MANANGED DATA govobj.UpdateSentinelVariables(pCurrentBlockIndex); - if(AddGovernanceObject(govobj)) - { - govobj.Relay(); - } + if(AddGovernanceObject(govobj)) govobj.Relay(); mapSeenGovernanceObjects.insert(make_pair(govobj.GetHash(), SEEN_OBJECT_IS_VALID)); masternodeSync.AddedBudgetItem(govobj.GetHash()); diff --git a/src/governance.h b/src/governance.h index d79a957d420e7..034409a7e013e 100644 --- a/src/governance.h +++ b/src/governance.h @@ -176,11 +176,11 @@ class CGovernanceObject std::string strLocalValidityError; // set via sentinel voting mechanisms - // caching -- one per voting mechanism -- see governance-vote.h for more information - bool fCachedFunding; - bool fCachedValid; - bool fCachedDelete; - bool fCachedEndorsed; + // caching -- one per voting mechanism -- see below for more information + bool fCachedFunding; // true == minimum network support has been reached for this object to be funded (doesn't mean it will for sure though) + bool fCachedValid; // true == minimum network has been reached flagging this object as a valid and understood goverance object (e.g, the serialized data is correct format, etc) + bool fCachedDelete; // true == minimum network support has been reached saying this object should be deleted from the system entirely + bool fCachedEndorsed; // true == minimum network support has been reached flagging this object as endorsed by an elected representative body (e.g. business review board / technecial review board /etc) CGovernanceObject(); CGovernanceObject(uint256 nHashParentIn, int nRevisionIn, std::string strNameIn, int64_t nTime, uint256 nFeeTXHashIn); From 390c9c39281eddc29eeff2e77fff7a544fbe01fe Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Thu, 9 Jun 2016 10:50:54 -0700 Subject: [PATCH 8/9] add dirty flag for future use --- src/governance.cpp | 36 +++++++++++++++++++----------------- src/governance.h | 2 +- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/governance.cpp b/src/governance.cpp index cf13d98fb31cd..2b66b632bc782 100644 --- a/src/governance.cpp +++ b/src/governance.cpp @@ -265,30 +265,24 @@ void CGovernanceManager::CheckAndRemove() std::map::iterator it = mapObjects.begin(); while(it != mapObjects.end()) - { + { CGovernanceObject* pObj = &((*it).second); + // UPDATE LOCAL VALIDITY AGAINST CRYPTO DATA pObj->UpdateLocalValidity(pCurrentBlockIndex); + // UPDATE SENTINEL SIGNALING VARIABLES pObj->UpdateSentinelVariables(pCurrentBlockIndex); - ++it; - } - // UPDATE CACHING MECHANISMS FOR GOVERNANCE OBJECTS + // SHOULD WE DELETE THIS OBJECT FROM MEMORY - std::string strError = ""; + /* + - delete objects from memory where fCachedDelete is true + - this should be robust enough that if someone sends us the proposal later, we should know it was deleted + */ - std::map::iterator it2 = mapObjects.begin(); - while(it2 != mapObjects.end()) - { - CGovernanceObject* pObj = &((*it2).second); - - // UPDATE LOCAL VALIDITY AGAINST CRYPTO DATA - pObj->UpdateLocalValidity(pCurrentBlockIndex); - - // UPDATE SENTINEL SIGNALING VARIABLES - pObj->UpdateSentinelVariables(pCurrentBlockIndex); - ++it2; + ++it; } + } CGovernanceObject *CGovernanceManager::FindGovernanceObject(const std::string &strName) @@ -541,6 +535,12 @@ bool CGovernanceManager::AddOrUpdateVote(const CGovernanceVote& vote, std::strin mapVotesByType[nTypeHash] = vote; mapVotesByHash[nHash] = vote; + + // // SET CACHE AS DIRTY / WILL BE UPDATED NEXT BLOCK + + // CGovernanceObject* pGovObj = FindGovernanceObject(vote.GetParentHash()); + // if(pGovObj) pGovObj->fDirtyCache = true; + return true; } @@ -558,7 +558,7 @@ CGovernanceObject::CGovernanceObject() fCachedValid = true; fCachedDelete = false; fCachedEndorsed = false; - + //fDirtyCache = true; } CGovernanceObject::CGovernanceObject(uint256 nHashParentIn, int nRevisionIn, std::string strNameIn, int64_t nTimeIn, uint256 nFeeTXHashIn) @@ -574,6 +574,7 @@ CGovernanceObject::CGovernanceObject(uint256 nHashParentIn, int nRevisionIn, std fCachedValid = true; fCachedDelete = false; fCachedEndorsed = false; + //fDirtyCache = true; } CGovernanceObject::CGovernanceObject(const CGovernanceObject& other) @@ -592,6 +593,7 @@ CGovernanceObject::CGovernanceObject(const CGovernanceObject& other) fCachedValid = other.fCachedValid; fCachedDelete = other.fCachedDelete; fCachedEndorsed = other.fCachedEndorsed; + //fDirtyCache = other.fDirtyCache; } bool CGovernanceObject::IsValid(const CBlockIndex* pindex, std::string& strError, bool fCheckCollateral) diff --git a/src/governance.h b/src/governance.h index 034409a7e013e..b1825edd7672d 100644 --- a/src/governance.h +++ b/src/governance.h @@ -181,6 +181,7 @@ class CGovernanceObject bool fCachedValid; // true == minimum network has been reached flagging this object as a valid and understood goverance object (e.g, the serialized data is correct format, etc) bool fCachedDelete; // true == minimum network support has been reached saying this object should be deleted from the system entirely bool fCachedEndorsed; // true == minimum network support has been reached flagging this object as endorsed by an elected representative body (e.g. business review board / technecial review board /etc) + // bool fDirtyCache; // object was updated and cached values should be updated soon CGovernanceObject(); CGovernanceObject(uint256 nHashParentIn, int nRevisionIn, std::string strNameIn, int64_t nTime, uint256 nFeeTXHashIn); @@ -257,7 +258,6 @@ class CGovernanceObject void CleanAndRemove(bool fSignatureCheck); void Relay(); - uint256 GetHash(){ // CREATE HASH OF ALL IMPORTANT PIECES OF DATA From b76304e622de5238f5b6819a795a1f910271ad14 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Thu, 9 Jun 2016 12:17:03 -0700 Subject: [PATCH 9/9] added other cached flags into output --- src/rpcmasternode-budget.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/rpcmasternode-budget.cpp b/src/rpcmasternode-budget.cpp index 2eaefad21af32..67c32b77f0b43 100644 --- a/src/rpcmasternode-budget.cpp +++ b/src/rpcmasternode-budget.cpp @@ -324,6 +324,9 @@ UniValue mngovernance(const UniValue& params, bool fHelp) bObj.push_back(Pair("IsValid", pbudgetProposal->IsValid(pindex, strError))); bObj.push_back(Pair("IsValidReason", strError.c_str())); bObj.push_back(Pair("fCachedValid", pbudgetProposal->fCachedValid)); + bObj.push_back(Pair("fCachedFunding", pbudgetProposal->fCachedFunding)); + bObj.push_back(Pair("fCachedDelete", pbudgetProposal->fCachedDelete)); + bObj.push_back(Pair("fCachedEndorsed", pbudgetProposal->fCachedEndorsed)); resultObj.push_back(Pair(pbudgetProposal->GetName(), bObj)); }