implement sentinel-like wd selection logic (#1359)

* Only accept wd's that are more recent or have a higher hash than the current best

* Fix whitespace typo

* Relay current watchdog when lower priority ones are received

* Fix nHashWatchdogCurrent reset conditions

* expire previous current wd when a new one is found in UpdateCurrentWatchdog

* fail to process votes for expired or deleted object
This commit is contained in:
UdjinM6 2017-02-22 22:29:30 +04:00 committed by GitHub
parent 17cf8dc6d1
commit 636fb33e71
2 changed files with 81 additions and 14 deletions

View File

@ -20,7 +20,7 @@ std::map<uint256, int64_t> mapAskedForGovernanceObject;
int nSubmittedFinalBudget; int nSubmittedFinalBudget;
const std::string CGovernanceManager::SERIALIZATION_VERSION_STRING = "CGovernanceManager-Version-9"; const std::string CGovernanceManager::SERIALIZATION_VERSION_STRING = "CGovernanceManager-Version-10";
CGovernanceManager::CGovernanceManager() CGovernanceManager::CGovernanceManager()
: pCurrentBlockIndex(NULL), : pCurrentBlockIndex(NULL),
@ -30,6 +30,8 @@ CGovernanceManager::CGovernanceManager()
mapSeenGovernanceObjects(), mapSeenGovernanceObjects(),
mapMasternodeOrphanObjects(), mapMasternodeOrphanObjects(),
mapWatchdogObjects(), mapWatchdogObjects(),
nHashWatchdogCurrent(),
nTimeWatchdogCurrent(0),
mapVoteToObject(MAX_CACHE_SIZE), mapVoteToObject(MAX_CACHE_SIZE),
mapInvalidVotes(MAX_CACHE_SIZE), mapInvalidVotes(MAX_CACHE_SIZE),
mapOrphanVotes(MAX_CACHE_SIZE), mapOrphanVotes(MAX_CACHE_SIZE),
@ -219,7 +221,7 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C
govobj.UpdateSentinelVariables(); //this sets local vars in object govobj.UpdateSentinelVariables(); //this sets local vars in object
if(AddGovernanceObject(govobj)) if(AddGovernanceObject(govobj, pfrom))
{ {
LogPrintf("MNGOVERNANCEOBJECT -- %s new\n", strHash); LogPrintf("MNGOVERNANCEOBJECT -- %s new\n", strHash);
govobj.Relay(); govobj.Relay();
@ -305,7 +307,7 @@ void CGovernanceManager::CheckOrphanVotes(CGovernanceObject& govobj, CGovernance
fRateChecksEnabled = true; fRateChecksEnabled = true;
} }
bool CGovernanceManager::AddGovernanceObject(CGovernanceObject& govobj) bool CGovernanceManager::AddGovernanceObject(CGovernanceObject& govobj, CNode* pfrom)
{ {
LOCK2(cs_main, cs); LOCK2(cs_main, cs);
std::string strError = ""; std::string strError = "";
@ -330,14 +332,23 @@ bool CGovernanceManager::AddGovernanceObject(CGovernanceObject& govobj)
LogPrint("gobject", "CGovernanceManager::AddGovernanceObject -- Adding object: hash = %s, type = %d\n", nHash.ToString(), govobj.GetObjectType()); LogPrint("gobject", "CGovernanceManager::AddGovernanceObject -- Adding object: hash = %s, type = %d\n", nHash.ToString(), govobj.GetObjectType());
// If it's a watchdog, make sure it fits required time bounds if(govobj.nObjectType == GOVERNANCE_OBJECT_WATCHDOG) {
if(govobj.nObjectType == GOVERNANCE_OBJECT_WATCHDOG && // If it's a watchdog, make sure it fits required time bounds
(govobj.GetCreationTime() < GetAdjustedTime() - GOVERNANCE_WATCHDOG_EXPIRATION_TIME || if((govobj.GetCreationTime() < GetAdjustedTime() - GOVERNANCE_WATCHDOG_EXPIRATION_TIME ||
govobj.GetCreationTime() > GetAdjustedTime() + GOVERNANCE_WATCHDOG_EXPIRATION_TIME) govobj.GetCreationTime() > GetAdjustedTime() + GOVERNANCE_WATCHDOG_EXPIRATION_TIME)
) { ) {
// drop it // drop it
LogPrint("gobject", "CGovernanceManager::AddGovernanceObject -- CreationTime is out of bounds: hash = %s\n", nHash.ToString()); LogPrint("gobject", "CGovernanceManager::AddGovernanceObject -- CreationTime is out of bounds: hash = %s\n", nHash.ToString());
return false; return false;
}
if(!UpdateCurrentWatchdog(govobj)) {
if(pfrom && (nHashWatchdogCurrent != uint256())) {
pfrom->PushInventory(CInv(MSG_GOVERNANCE_OBJECT, nHashWatchdogCurrent));
}
LogPrint("gobject", "CGovernanceManager::AddGovernanceObject -- Watchdog not better than current: hash = %s\n", nHash.ToString());
return false;
}
} }
// INSERT INTO OUR GOVERNANCE OBJECT MEMORY // INSERT INTO OUR GOVERNANCE OBJECT MEMORY
@ -369,6 +380,38 @@ bool CGovernanceManager::AddGovernanceObject(CGovernanceObject& govobj)
return true; return true;
} }
bool CGovernanceManager::UpdateCurrentWatchdog(CGovernanceObject& watchdogNew)
{
bool fAccept = false;
arith_uint256 nHashNew = UintToArith256(watchdogNew.GetHash());
arith_uint256 nHashCurrent = UintToArith256(nHashWatchdogCurrent);
int64_t nExpirationDelay = GOVERNANCE_WATCHDOG_EXPIRATION_TIME / 2;
int64_t nNow = GetTime();
if((nHashWatchdogCurrent == uint256()) ||
(((nNow - nTimeWatchdogCurrent) > nExpirationDelay) && (nNow - watchdogNew.GetCreationTime() < nExpirationDelay)) ||
(nHashNew > nHashCurrent)) {
LOCK(cs);
object_m_it it = mapObjects.find(nHashWatchdogCurrent);
if(it != mapObjects.end()) {
LogPrint("gobject", "CGovernanceManager::UpdateCurrentWatchdog -- Expiring previous current watchdog, hash = %s\n", nHashWatchdogCurrent.ToString());
it->second.fExpired = true;
if(it->second.nDeletionTime == 0) {
it->second.nDeletionTime = nNow;
}
}
nHashWatchdogCurrent = watchdogNew.GetHash();
nTimeWatchdogCurrent = watchdogNew.GetCreationTime();
fAccept = true;
LogPrint("gobject", "CGovernanceManager::UpdateCurrentWatchdog -- Current watchdog updated to: hash = %s\n",
ArithToUint256(nHashNew).ToString());
}
return fAccept;
}
void CGovernanceManager::UpdateCachesAndClean() void CGovernanceManager::UpdateCachesAndClean()
{ {
LogPrint("gobject", "CGovernanceManager::UpdateCachesAndClean\n"); LogPrint("gobject", "CGovernanceManager::UpdateCachesAndClean\n");
@ -394,6 +437,9 @@ void CGovernanceManager::UpdateCachesAndClean()
it2->second.nDeletionTime = nNow; it2->second.nDeletionTime = nNow;
} }
} }
if(it->first == nHashWatchdogCurrent) {
nHashWatchdogCurrent = uint256();
}
mapWatchdogObjects.erase(it++); mapWatchdogObjects.erase(it++);
} }
else { else {
@ -435,7 +481,8 @@ void CGovernanceManager::UpdateCachesAndClean()
continue; continue;
} }
std::string strHash = pObj->GetHash().ToString(); uint256 nHash = it->first;
std::string strHash = nHash.ToString();
// IF CACHE IS NOT DIRTY, WHY DO THIS? // IF CACHE IS NOT DIRTY, WHY DO THIS?
if(pObj->IsSetDirtyCache()) { if(pObj->IsSetDirtyCache()) {
@ -446,6 +493,10 @@ void CGovernanceManager::UpdateCachesAndClean()
pObj->UpdateSentinelVariables(); pObj->UpdateSentinelVariables();
} }
if(pObj->IsSetCachedDelete() && (nHash == nHashWatchdogCurrent)) {
nHashWatchdogCurrent = uint256();
}
// IF DELETE=TRUE, THEN CLEAN THE MESS UP! // IF DELETE=TRUE, THEN CLEAN THE MESS UP!
int64_t nTimeSinceDeletion = GetAdjustedTime() - pObj->GetDeletionTime(); int64_t nTimeSinceDeletion = GetAdjustedTime() - pObj->GetDeletionTime();
@ -471,7 +522,7 @@ void CGovernanceManager::UpdateCachesAndClean()
++lit; ++lit;
} }
} }
if(pObj->nObjectType == GOVERNANCE_OBJECT_WATCHDOG && pObj->IsSetCachedDelete()) { if(pObj->nObjectType == GOVERNANCE_OBJECT_WATCHDOG) {
mapWatchdogObjects.erase(it->first); mapWatchdogObjects.erase(it->first);
} }
mapObjects.erase(it++); mapObjects.erase(it++);
@ -903,6 +954,12 @@ bool CGovernanceManager::ProcessVote(CNode* pfrom, const CGovernanceVote& vote,
} }
CGovernanceObject& govobj = it->second; CGovernanceObject& govobj = it->second;
if(govobj.IsSetCachedDelete() || govobj.IsSetExpired()) {
LogPrint("gobject", "CGovernanceObject::ProcessVote -- ignoring vote for expired or deleted object, hash = %s\n", nHashGovobj.ToString());
return false;
}
bool fOk = govobj.ProcessVote(pfrom, vote, exception); bool fOk = govobj.ProcessVote(pfrom, vote, exception);
if(fOk) { if(fOk) {
mapVoteToObject.Insert(nHashVote, &govobj); mapVoteToObject.Insert(nHashVote, &govobj);

View File

@ -236,6 +236,10 @@ private:
hash_time_m_t mapWatchdogObjects; hash_time_m_t mapWatchdogObjects;
uint256 nHashWatchdogCurrent;
int64_t nTimeWatchdogCurrent;
object_ref_cache_t mapVoteToObject; object_ref_cache_t mapVoteToObject;
vote_cache_t mapInvalidVotes; vote_cache_t mapInvalidVotes;
@ -285,7 +289,7 @@ public:
std::vector<CGovernanceObject*> GetAllNewerThan(int64_t nMoreThanTime); std::vector<CGovernanceObject*> GetAllNewerThan(int64_t nMoreThanTime);
bool IsBudgetPaymentBlock(int nBlockHeight); bool IsBudgetPaymentBlock(int nBlockHeight);
bool AddGovernanceObject (CGovernanceObject& govobj); bool AddGovernanceObject(CGovernanceObject& govobj, CNode* pfrom = NULL);
std::string GetRequiredPaymentsString(int nBlockHeight); std::string GetRequiredPaymentsString(int nBlockHeight);
@ -301,6 +305,8 @@ public:
mapObjects.clear(); mapObjects.clear();
mapSeenGovernanceObjects.clear(); mapSeenGovernanceObjects.clear();
mapWatchdogObjects.clear(); mapWatchdogObjects.clear();
nHashWatchdogCurrent = uint256();
nTimeWatchdogCurrent = 0;
mapVoteToObject.Clear(); mapVoteToObject.Clear();
mapInvalidVotes.Clear(); mapInvalidVotes.Clear();
mapOrphanVotes.Clear(); mapOrphanVotes.Clear();
@ -327,6 +333,8 @@ public:
READWRITE(mapOrphanVotes); READWRITE(mapOrphanVotes);
READWRITE(mapObjects); READWRITE(mapObjects);
READWRITE(mapWatchdogObjects); READWRITE(mapWatchdogObjects);
READWRITE(nHashWatchdogCurrent);
READWRITE(nTimeWatchdogCurrent);
READWRITE(mapLastMasternodeObject); READWRITE(mapLastMasternodeObject);
if(ser_action.ForRead() && (strVersion != SERIALIZATION_VERSION_STRING)) { if(ser_action.ForRead() && (strVersion != SERIALIZATION_VERSION_STRING)) {
Clear(); Clear();
@ -415,6 +423,8 @@ private:
void AddCachedTriggers(); void AddCachedTriggers();
bool UpdateCurrentWatchdog(CGovernanceObject& watchdogNew);
}; };
#endif #endif