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;
const std::string CGovernanceManager::SERIALIZATION_VERSION_STRING = "CGovernanceManager-Version-9";
const std::string CGovernanceManager::SERIALIZATION_VERSION_STRING = "CGovernanceManager-Version-10";
CGovernanceManager::CGovernanceManager()
: pCurrentBlockIndex(NULL),
@ -30,6 +30,8 @@ CGovernanceManager::CGovernanceManager()
mapSeenGovernanceObjects(),
mapMasternodeOrphanObjects(),
mapWatchdogObjects(),
nHashWatchdogCurrent(),
nTimeWatchdogCurrent(0),
mapVoteToObject(MAX_CACHE_SIZE),
mapInvalidVotes(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
if(AddGovernanceObject(govobj))
if(AddGovernanceObject(govobj, pfrom))
{
LogPrintf("MNGOVERNANCEOBJECT -- %s new\n", strHash);
govobj.Relay();
@ -305,7 +307,7 @@ void CGovernanceManager::CheckOrphanVotes(CGovernanceObject& govobj, CGovernance
fRateChecksEnabled = true;
}
bool CGovernanceManager::AddGovernanceObject(CGovernanceObject& govobj)
bool CGovernanceManager::AddGovernanceObject(CGovernanceObject& govobj, CNode* pfrom)
{
LOCK2(cs_main, cs);
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());
// If it's a watchdog, make sure it fits required time bounds
if(govobj.nObjectType == GOVERNANCE_OBJECT_WATCHDOG &&
(govobj.GetCreationTime() < GetAdjustedTime() - GOVERNANCE_WATCHDOG_EXPIRATION_TIME ||
govobj.GetCreationTime() > GetAdjustedTime() + GOVERNANCE_WATCHDOG_EXPIRATION_TIME)
) {
// drop it
LogPrint("gobject", "CGovernanceManager::AddGovernanceObject -- CreationTime is out of bounds: hash = %s\n", nHash.ToString());
return false;
if(govobj.nObjectType == GOVERNANCE_OBJECT_WATCHDOG) {
// If it's a watchdog, make sure it fits required time bounds
if((govobj.GetCreationTime() < GetAdjustedTime() - GOVERNANCE_WATCHDOG_EXPIRATION_TIME ||
govobj.GetCreationTime() > GetAdjustedTime() + GOVERNANCE_WATCHDOG_EXPIRATION_TIME)
) {
// drop it
LogPrint("gobject", "CGovernanceManager::AddGovernanceObject -- CreationTime is out of bounds: hash = %s\n", nHash.ToString());
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
@ -369,6 +380,38 @@ bool CGovernanceManager::AddGovernanceObject(CGovernanceObject& govobj)
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()
{
LogPrint("gobject", "CGovernanceManager::UpdateCachesAndClean\n");
@ -394,6 +437,9 @@ void CGovernanceManager::UpdateCachesAndClean()
it2->second.nDeletionTime = nNow;
}
}
if(it->first == nHashWatchdogCurrent) {
nHashWatchdogCurrent = uint256();
}
mapWatchdogObjects.erase(it++);
}
else {
@ -435,7 +481,8 @@ void CGovernanceManager::UpdateCachesAndClean()
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(pObj->IsSetDirtyCache()) {
@ -446,6 +493,10 @@ void CGovernanceManager::UpdateCachesAndClean()
pObj->UpdateSentinelVariables();
}
if(pObj->IsSetCachedDelete() && (nHash == nHashWatchdogCurrent)) {
nHashWatchdogCurrent = uint256();
}
// IF DELETE=TRUE, THEN CLEAN THE MESS UP!
int64_t nTimeSinceDeletion = GetAdjustedTime() - pObj->GetDeletionTime();
@ -471,7 +522,7 @@ void CGovernanceManager::UpdateCachesAndClean()
++lit;
}
}
if(pObj->nObjectType == GOVERNANCE_OBJECT_WATCHDOG && pObj->IsSetCachedDelete()) {
if(pObj->nObjectType == GOVERNANCE_OBJECT_WATCHDOG) {
mapWatchdogObjects.erase(it->first);
}
mapObjects.erase(it++);
@ -903,6 +954,12 @@ bool CGovernanceManager::ProcessVote(CNode* pfrom, const CGovernanceVote& vote,
}
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);
if(fOk) {
mapVoteToObject.Insert(nHashVote, &govobj);

View File

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