V0.12.1.x multiple wd rate check (#1426)

* Modify MasternodeRateCheck to support updating buffers only on failure

* Update rate check buffer only when fAddToSeen is true
This commit is contained in:
Tim Flynn 2017-04-05 12:30:08 -04:00 committed by UdjinM6
parent d7fbaf907f
commit 86525601d5
3 changed files with 48 additions and 30 deletions

View File

@ -186,7 +186,7 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C
} }
bool fRateCheckBypassed = false; bool fRateCheckBypassed = false;
if(!MasternodeRateCheck(govobj, true, false, fRateCheckBypassed)) { if(!MasternodeRateCheck(govobj, UPDATE_FAIL_ONLY, false, fRateCheckBypassed)) {
LogPrintf("MNGOVERNANCEOBJECT -- masternode rate check failed - %s - (current block height %d) \n", strHash, nCachedBlockHeight); LogPrintf("MNGOVERNANCEOBJECT -- masternode rate check failed - %s - (current block height %d) \n", strHash, nCachedBlockHeight);
return; return;
} }
@ -209,7 +209,7 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C
} }
if(fRateCheckBypassed) { if(fRateCheckBypassed) {
if(!MasternodeRateCheck(govobj, true, true, fRateCheckBypassed)) { if(!MasternodeRateCheck(govobj, UPDATE_FAIL_ONLY, true, fRateCheckBypassed)) {
LogPrintf("MNGOVERNANCEOBJECT -- masternode rate check failed (after signature verification) - %s - (current block height %d) \n", strHash, nCachedBlockHeight); LogPrintf("MNGOVERNANCEOBJECT -- masternode rate check failed (after signature verification) - %s - (current block height %d) \n", strHash, nCachedBlockHeight);
return; return;
} }
@ -229,6 +229,8 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C
if(fAddToSeen) { if(fAddToSeen) {
// UPDATE THAT WE'VE SEEN THIS OBJECT // UPDATE THAT WE'VE SEEN THIS OBJECT
mapSeenGovernanceObjects.insert(std::make_pair(nHash, SEEN_OBJECT_IS_VALID)); mapSeenGovernanceObjects.insert(std::make_pair(nHash, SEEN_OBJECT_IS_VALID));
// Update the rate buffer
MasternodeRateCheck(govobj, UPDATE_TRUE, true, fRateCheckBypassed);
} }
masternodeSync.AddedGovernanceItem(); masternodeSync.AddedGovernanceItem();
@ -814,13 +816,13 @@ void CGovernanceManager::Sync(CNode* pfrom, const uint256& nProp, const CBloomFi
LogPrintf("CGovernanceManager::Sync -- sent %d objects and %d votes to peer=%d\n", nObjCount, nVoteCount, pfrom->id); LogPrintf("CGovernanceManager::Sync -- sent %d objects and %d votes to peer=%d\n", nObjCount, nVoteCount, pfrom->id);
} }
bool CGovernanceManager::MasternodeRateCheck(const CGovernanceObject& govobj, bool fUpdateLast) bool CGovernanceManager::MasternodeRateCheck(const CGovernanceObject& govobj, update_mode_enum_t eUpdateLast)
{ {
bool fRateCheckBypassed = false; bool fRateCheckBypassed = false;
return MasternodeRateCheck(govobj, fUpdateLast, true, fRateCheckBypassed); return MasternodeRateCheck(govobj, eUpdateLast, true, fRateCheckBypassed);
} }
bool CGovernanceManager::MasternodeRateCheck(const CGovernanceObject& govobj, bool fUpdateLast, bool fForce, bool& fRateCheckBypassed) bool CGovernanceManager::MasternodeRateCheck(const CGovernanceObject& govobj, update_mode_enum_t eUpdateLast, bool fForce, bool& fRateCheckBypassed)
{ {
LOCK(cs); LOCK(cs);
@ -848,7 +850,7 @@ bool CGovernanceManager::MasternodeRateCheck(const CGovernanceObject& govobj, bo
txout_m_it it = mapLastMasternodeObject.find(vin.prevout); txout_m_it it = mapLastMasternodeObject.find(vin.prevout);
if(it == mapLastMasternodeObject.end()) { if(it == mapLastMasternodeObject.end()) {
if(fUpdateLast) { if(eUpdateLast == UPDATE_TRUE) {
it = mapLastMasternodeObject.insert(txout_m_t::value_type(vin.prevout, last_object_rec(true))).first; it = mapLastMasternodeObject.insert(txout_m_t::value_type(vin.prevout, last_object_rec(true))).first;
switch(nObjectType) { switch(nObjectType) {
case GOVERNANCE_OBJECT_TRIGGER: case GOVERNANCE_OBJECT_TRIGGER:
@ -886,44 +888,54 @@ bool CGovernanceManager::MasternodeRateCheck(const CGovernanceObject& govobj, bo
double dMaxRate = 1.1 / nSuperblockCycleSeconds; double dMaxRate = 1.1 / nSuperblockCycleSeconds;
double dRate = 0.0; double dRate = 0.0;
CRateCheckBuffer buffer; CRateCheckBuffer buffer;
CRateCheckBuffer* pBuffer = NULL;
switch(nObjectType) { switch(nObjectType) {
case GOVERNANCE_OBJECT_TRIGGER: case GOVERNANCE_OBJECT_TRIGGER:
// Allow 1 trigger per mn per cycle, with a small fudge factor // Allow 1 trigger per mn per cycle, with a small fudge factor
pBuffer = &it->second.triggerBuffer;
dMaxRate = 2 * 1.1 / double(nSuperblockCycleSeconds); dMaxRate = 2 * 1.1 / double(nSuperblockCycleSeconds);
buffer = it->second.triggerBuffer;
buffer.AddTimestamp(nTimestamp);
dRate = buffer.GetRate();
if(fUpdateLast) {
it->second.triggerBuffer.AddTimestamp(nTimestamp);
}
break; break;
case GOVERNANCE_OBJECT_WATCHDOG: case GOVERNANCE_OBJECT_WATCHDOG:
pBuffer = &it->second.watchdogBuffer;
dMaxRate = 2 * 1.1 / 3600.; dMaxRate = 2 * 1.1 / 3600.;
buffer = it->second.watchdogBuffer;
buffer.AddTimestamp(nTimestamp);
dRate = buffer.GetRate();
if(fUpdateLast) {
it->second.watchdogBuffer.AddTimestamp(nTimestamp);
}
break; break;
default: default:
break; break;
} }
if(dRate < dMaxRate) { if(!pBuffer) {
if(fUpdateLast) { LogPrintf("CGovernanceManager::MasternodeRateCheck -- Internal Error returning false, NULL ptr found for object %s masternode vin = %s, timestamp = %d, current time = %d\n",
it->second.fStatusOK = true; strHash, vin.prevout.ToStringShort(), nTimestamp, nNow);
return false;
} }
buffer = *pBuffer;
buffer.AddTimestamp(nTimestamp);
dRate = buffer.GetRate();
bool fRateOK = ( dRate < dMaxRate );
switch(eUpdateLast) {
case UPDATE_TRUE:
pBuffer->AddTimestamp(nTimestamp);
it->second.fStatusOK = fRateOK;
break;
case UPDATE_FAIL_ONLY:
if(!fRateOK) {
pBuffer->AddTimestamp(nTimestamp);
it->second.fStatusOK = false;
}
default:
return true;
}
if(fRateOK) {
return true; return true;
} }
else { else {
if(fUpdateLast) {
it->second.fStatusOK = false;
}
}
LogPrintf("CGovernanceManager::MasternodeRateCheck -- Rate too high: object hash = %s, masternode vin = %s, object timestamp = %d, rate = %f, max rate = %f\n", LogPrintf("CGovernanceManager::MasternodeRateCheck -- Rate too high: object hash = %s, masternode vin = %s, object timestamp = %d, rate = %f, max rate = %f\n",
strHash, vin.prevout.ToStringShort(), nTimestamp, dRate, dMaxRate); strHash, vin.prevout.ToStringShort(), nTimestamp, dRate, dMaxRate);
}
return false; return false;
} }

View File

@ -134,6 +134,12 @@ public:
} }
}; };
enum update_mode_enum_t {
UPDATE_FALSE,
UPDATE_TRUE,
UPDATE_FAIL_ONLY
};
// //
// Governance Manager : Contains all proposals for the budget // Governance Manager : Contains all proposals for the budget
// //
@ -362,9 +368,9 @@ public:
void AddSeenVote(uint256 nHash, int status); void AddSeenVote(uint256 nHash, int status);
bool MasternodeRateCheck(const CGovernanceObject& govobj, bool fUpdateLast = false); bool MasternodeRateCheck(const CGovernanceObject& govobj, update_mode_enum_t eUpdateLast = UPDATE_FALSE);
bool MasternodeRateCheck(const CGovernanceObject& govobj, bool fUpdateLast, bool fForce, bool& fRateCheckBypassed); bool MasternodeRateCheck(const CGovernanceObject& govobj, update_mode_enum_t eUpdateLast, bool fForce, bool& fRateCheckBypassed);
bool ProcessVoteAndRelay(const CGovernanceVote& vote, CGovernanceException& exception) { bool ProcessVoteAndRelay(const CGovernanceVote& vote, CGovernanceException& exception) {
bool fOK = ProcessVote(NULL, vote, exception); bool fOK = ProcessVote(NULL, vote, exception);

View File

@ -214,7 +214,7 @@ UniValue gobject(const UniValue& params, bool fHelp)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Object creation rate limit exceeded"); throw JSONRPCError(RPC_INVALID_PARAMETER, "Object creation rate limit exceeded");
} }
// This check should always pass, update buffer // This check should always pass, update buffer
if(!governance.MasternodeRateCheck(govobj, true)) { if(!governance.MasternodeRateCheck(govobj, UPDATE_TRUE)) {
LogPrintf("gobject(submit) -- Object submission rejected because of rate check failure (buffer updated) - hash = %s\n", strHash); LogPrintf("gobject(submit) -- Object submission rejected because of rate check failure (buffer updated) - hash = %s\n", strHash);
throw JSONRPCError(RPC_INVALID_PARAMETER, "Object creation rate limit exceeded"); throw JSONRPCError(RPC_INVALID_PARAMETER, "Object creation rate limit exceeded");
} }