Merge remote-tracking branch 'remotes/origin/master' into v0.12.2.x

# Conflicts:
#	configure.ac
#	src/clientversion.h
This commit is contained in:
Holger Schinzel 2017-04-11 11:19:18 +02:00
commit b815a7b6a3
8 changed files with 110 additions and 47 deletions

View File

@ -178,9 +178,19 @@ bool CGovernanceObject::ProcessVote(CNode* pfrom,
governance.AddInvalidVote(vote);
return false;
}
if(!mnodeman.AddGovernanceVote(vote.GetVinMasternode(), vote.GetParentHash())) {
std::ostringstream ostr;
ostr << "CGovernanceObject::ProcessVote -- Unable to add governance vote "
<< ", MN outpoint = " << vote.GetVinMasternode().prevout.ToStringShort()
<< ", governance object hash = " << GetHash().ToString() << "\n";
LogPrint("gobject", ostr.str().c_str());
exception = CGovernanceException(ostr.str(), GOVERNANCE_EXCEPTION_PERMANENT_ERROR);
return false;
}
voteInstance = vote_instance_t(vote.GetOutcome(), nVoteTimeUpdate, vote.GetTimestamp());
fileVotes.AddVote(vote);
mnodeman.AddGovernanceVote(vote.GetVinMasternode(), vote.GetParentHash());
if(!fileVotes.HasVote(vote.GetHash())) {
fileVotes.AddVote(vote);
}
fDirtyCache = true;
return true;
}

View File

@ -58,6 +58,7 @@ void CGovernanceObjectVoteFile::RemoveVotesFromMasternode(const CTxIn& vinMaster
vote_l_it it = listVotes.begin();
while(it != listVotes.end()) {
if(it->GetVinMasternode() == vinMasternode) {
--nMemoryVotes;
mapVoteIndex.erase(it->GetHash());
listVotes.erase(it++);
}
@ -78,8 +79,18 @@ CGovernanceObjectVoteFile& CGovernanceObjectVoteFile::operator=(const CGovernanc
void CGovernanceObjectVoteFile::RebuildIndex()
{
mapVoteIndex.clear();
for(vote_l_it it = listVotes.begin(); it != listVotes.end(); ++it) {
nMemoryVotes = 0;
vote_l_it it = listVotes.begin();
while(it != listVotes.end()) {
CGovernanceVote& vote = *it;
mapVoteIndex[vote.GetHash()] = it;
uint256 nHash = vote.GetHash();
if(mapVoteIndex.find(nHash) == mapVoteIndex.end()) {
mapVoteIndex[nHash] = it;
++nMemoryVotes;
++it;
}
else {
listVotes.erase(it++);
}
}
}

View File

@ -186,7 +186,7 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C
}
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);
return;
}
@ -209,7 +209,7 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C
}
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);
return;
}
@ -219,14 +219,20 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C
govobj.UpdateSentinelVariables(); //this sets local vars in object
if(AddGovernanceObject(govobj, pfrom))
bool fAddToSeen = true;
if(AddGovernanceObject(govobj, fAddToSeen, pfrom))
{
LogPrintf("MNGOVERNANCEOBJECT -- %s new\n", strHash);
govobj.Relay();
}
// UPDATE THAT WE'VE SEEN THIS OBJECT
mapSeenGovernanceObjects.insert(std::make_pair(nHash, SEEN_OBJECT_IS_VALID));
if(fAddToSeen) {
// UPDATE THAT WE'VE SEEN THIS OBJECT
mapSeenGovernanceObjects.insert(std::make_pair(nHash, SEEN_OBJECT_IS_VALID));
// Update the rate buffer
MasternodeRateCheck(govobj, UPDATE_TRUE, true, fRateCheckBypassed);
}
masternodeSync.AddedGovernanceItem();
@ -305,13 +311,15 @@ void CGovernanceManager::CheckOrphanVotes(CGovernanceObject& govobj, CGovernance
fRateChecksEnabled = true;
}
bool CGovernanceManager::AddGovernanceObject(CGovernanceObject& govobj, CNode* pfrom)
bool CGovernanceManager::AddGovernanceObject(CGovernanceObject& govobj, bool& fAddToSeen, CNode* pfrom)
{
LOCK2(cs_main, cs);
std::string strError = "";
DBG( cout << "CGovernanceManager::AddGovernanceObject START" << endl; );
fAddToSeen = true;
uint256 nHash = govobj.GetHash();
// MAKE SURE THIS OBJECT IS OK
@ -341,6 +349,8 @@ bool CGovernanceManager::AddGovernanceObject(CGovernanceObject& govobj, CNode* p
}
if(!UpdateCurrentWatchdog(govobj)) {
// Allow wd's which are not current to be reprocessed
fAddToSeen = false;
if(pfrom && (nHashWatchdogCurrent != uint256())) {
pfrom->PushInventory(CInv(MSG_GOVERNANCE_OBJECT, nHashWatchdogCurrent));
}
@ -806,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);
}
bool CGovernanceManager::MasternodeRateCheck(const CGovernanceObject& govobj, bool fUpdateLast)
bool CGovernanceManager::MasternodeRateCheck(const CGovernanceObject& govobj, update_mode_enum_t eUpdateLast)
{
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);
@ -840,7 +850,7 @@ bool CGovernanceManager::MasternodeRateCheck(const CGovernanceObject& govobj, bo
txout_m_it it = mapLastMasternodeObject.find(vin.prevout);
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;
switch(nObjectType) {
case GOVERNANCE_OBJECT_TRIGGER:
@ -878,44 +888,54 @@ bool CGovernanceManager::MasternodeRateCheck(const CGovernanceObject& govobj, bo
double dMaxRate = 1.1 / nSuperblockCycleSeconds;
double dRate = 0.0;
CRateCheckBuffer buffer;
CRateCheckBuffer* pBuffer = NULL;
switch(nObjectType) {
case GOVERNANCE_OBJECT_TRIGGER:
// Allow 1 trigger per mn per cycle, with a small fudge factor
pBuffer = &it->second.triggerBuffer;
dMaxRate = 2 * 1.1 / double(nSuperblockCycleSeconds);
buffer = it->second.triggerBuffer;
buffer.AddTimestamp(nTimestamp);
dRate = buffer.GetRate();
if(fUpdateLast) {
it->second.triggerBuffer.AddTimestamp(nTimestamp);
}
break;
case GOVERNANCE_OBJECT_WATCHDOG:
pBuffer = &it->second.watchdogBuffer;
dMaxRate = 2 * 1.1 / 3600.;
buffer = it->second.watchdogBuffer;
buffer.AddTimestamp(nTimestamp);
dRate = buffer.GetRate();
if(fUpdateLast) {
it->second.watchdogBuffer.AddTimestamp(nTimestamp);
}
break;
default:
break;
}
if(dRate < dMaxRate) {
if(fUpdateLast) {
it->second.fStatusOK = true;
if(!pBuffer) {
LogPrintf("CGovernanceManager::MasternodeRateCheck -- Internal Error returning false, NULL ptr found for object %s masternode vin = %s, timestamp = %d, current time = %d\n",
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;
}
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",
strHash, vin.prevout.ToStringShort(), nTimestamp, dRate, dMaxRate);
}
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);
return false;
}
@ -1007,7 +1027,8 @@ void CGovernanceManager::CheckMasternodeOrphanObjects()
continue;
}
if(AddGovernanceObject(govobj)) {
bool fAddToSeen = true;
if(AddGovernanceObject(govobj, fAddToSeen)) {
LogPrintf("CGovernanceManager::CheckMasternodeOrphanObjects -- %s new\n", govobj.GetHash().ToString());
govobj.Relay();
mapMasternodeOrphanObjects.erase(it++);

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
//
@ -288,7 +294,7 @@ public:
std::vector<CGovernanceObject*> GetAllNewerThan(int64_t nMoreThanTime);
bool IsBudgetPaymentBlock(int nBlockHeight);
bool AddGovernanceObject(CGovernanceObject& govobj, CNode* pfrom = NULL);
bool AddGovernanceObject(CGovernanceObject& govobj, bool& fAddToSeen, CNode* pfrom = NULL);
std::string GetRequiredPaymentsString(int nBlockHeight);
@ -362,9 +368,9 @@ public:
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 fOK = ProcessVote(NULL, vote, exception);

View File

@ -687,6 +687,12 @@ bool CMasternodePaymentVote::IsValid(CNode* pnode, int nValidationHeight, std::s
int nRank = mnodeman.GetMasternodeRank(vinMasternode, nBlockHeight - 101, nMinRequiredProtocol, false);
if(nRank == -1) {
LogPrint("mnpayments", "CMasternodePaymentVote::IsValid -- Can't calculate rank for masternode %s\n",
vinMasternode.prevout.ToStringShort());
return false;
}
if(nRank > MNPAYMENTS_SIGNATURES_TOTAL) {
// It's common to have masternodes mistakenly think they are in the top 10
// We don't want to print all of these messages in normal mode, debug mode should print though

View File

@ -1293,9 +1293,16 @@ void CMasternodeMan::ProcessVerifyBroadcast(CNode* pnode, const CMasternodeVerif
}
int nRank = GetMasternodeRank(mnv.vin2, mnv.nBlockHeight, MIN_POSE_PROTO_VERSION);
if(nRank < MAX_POSE_RANK) {
LogPrint("masternode", "MasternodeMan::ProcessVerifyBroadcast -- Mastrernode is not in top %d, current rank %d, peer=%d\n",
(int)MAX_POSE_RANK, nRank, pnode->id);
if (nRank == -1) {
LogPrint("masternode", "CMasternodeMan::ProcessVerifyBroadcast -- Can't calculate rank for masternode %s\n",
mnv.vin2.prevout.ToStringShort());
return;
}
if(nRank > MAX_POSE_RANK) {
LogPrint("masternode", "CMasternodeMan::ProcessVerifyBroadcast -- Mastrernode %s is not in top %d, current rank %d, peer=%d\n",
mnv.vin2.prevout.ToStringShort(), (int)MAX_POSE_RANK, nRank, pnode->id);
return;
}
@ -1548,14 +1555,15 @@ bool CMasternodeMan::IsWatchdogActive()
return (GetTime() - nLastWatchdogVoteTime) <= MASTERNODE_WATCHDOG_MAX_SECONDS;
}
void CMasternodeMan::AddGovernanceVote(const CTxIn& vin, uint256 nGovernanceObjectHash)
bool CMasternodeMan::AddGovernanceVote(const CTxIn& vin, uint256 nGovernanceObjectHash)
{
LOCK(cs);
CMasternode* pMN = Find(vin);
if(!pMN) {
return;
return false;
}
pMN->AddGovernanceVote(nGovernanceObjectHash);
return true;
}
void CMasternodeMan::RemoveGovernanceObject(uint256 nGovernanceObjectHash)

View File

@ -341,7 +341,7 @@ public:
bool IsWatchdogActive();
void UpdateWatchdogVoteTime(const CTxIn& vin);
void AddGovernanceVote(const CTxIn& vin, uint256 nGovernanceObjectHash);
bool AddGovernanceVote(const CTxIn& vin, uint256 nGovernanceObjectHash);
void RemoveGovernanceObject(uint256 nGovernanceObjectHash);
void CheckMasternode(const CTxIn& vin, bool fForce = false);

View File

@ -214,14 +214,15 @@ UniValue gobject(const UniValue& params, bool fHelp)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Object creation rate limit exceeded");
}
// 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);
throw JSONRPCError(RPC_INVALID_PARAMETER, "Object creation rate limit exceeded");
}
governance.AddSeenGovernanceObject(govobj.GetHash(), SEEN_OBJECT_IS_VALID);
govobj.Relay();
LogPrintf("gobject(submit) -- Adding locally created governance object - %s\n", strHash);
governance.AddGovernanceObject(govobj);
bool fAddToSeen = true;
governance.AddGovernanceObject(govobj, fAddToSeen);
return govobj.GetHash().ToString();
}