dash/src/masternodeman.cpp

1767 lines
70 KiB
C++
Raw Normal View History

2016-12-20 14:26:45 +01:00
// Copyright (c) 2014-2017 The Dash Core developers
2015-02-24 15:02:22 +01:00
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "activemasternode.h"
#include "addrman.h"
#include "alert.h"
#include "clientversion.h"
#include "governance.h"
#include "masternode-payments.h"
#include "masternode-sync.h"
#include "masternodeman.h"
#include "messagesigner.h"
2016-10-20 23:11:30 +02:00
#include "netfulfilledman.h"
#include "netmessagemaker.h"
#ifdef ENABLE_WALLET
#include "privatesend-client.h"
#endif // ENABLE_WALLET
#include "script/standard.h"
#include "ui_interface.h"
#include "util.h"
#include "warnings.h"
/** Masternode manager */
CMasternodeMan mnodeman;
const std::string CMasternodeMan::SERIALIZATION_VERSION_STRING = "CMasternodeMan-Version-7";
const int CMasternodeMan::LAST_PAID_SCAN_BLOCKS = 100;
2016-10-20 23:11:30 +02:00
struct CompareLastPaidBlock
{
bool operator()(const std::pair<int, const CMasternode*>& t1,
const std::pair<int, const CMasternode*>& t2) const
{
return (t1.first != t2.first) ? (t1.first < t2.first) : (t1.second->outpoint < t2.second->outpoint);
}
};
struct CompareScoreMN
{
bool operator()(const std::pair<arith_uint256, const CMasternode*>& t1,
const std::pair<arith_uint256, const CMasternode*>& t2) const
{
return (t1.first != t2.first) ? (t1.first < t2.first) : (t1.second->outpoint < t2.second->outpoint);
}
};
2016-10-20 23:11:30 +02:00
struct CompareByAddr
2016-10-20 23:11:30 +02:00
{
bool operator()(const CMasternode* t1,
const CMasternode* t2) const
{
return t1->addr < t2->addr;
}
};
CMasternodeMan::CMasternodeMan():
cs(),
mapMasternodes(),
mAskedUsForMasternodeList(),
mWeAskedForMasternodeList(),
mWeAskedForMasternodeListEntry(),
mWeAskedForVerification(),
mMnbRecoveryRequests(),
mMnbRecoveryGoodReplies(),
listScheduledMnbRequestConnections(),
fMasternodesAdded(false),
fMasternodesRemoved(false),
vecDirtyGovernanceObjectHashes(),
nLastSentinelPingTime(0),
mapSeenMasternodeBroadcast(),
mapSeenMasternodePing(),
nDsqCount(0)
{}
bool CMasternodeMan::Add(CMasternode &mn)
{
LOCK(cs);
if (Has(mn.outpoint)) return false;
2017-08-25 14:57:19 +02:00
LogPrint("masternode", "CMasternodeMan::Add -- Adding new Masternode: addr=%s, %i now\n", mn.addr.ToString(), size() + 1);
mapMasternodes[mn.outpoint] = mn;
2017-08-25 14:57:19 +02:00
fMasternodesAdded = true;
return true;
}
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
void CMasternodeMan::AskForMN(CNode* pnode, const COutPoint& outpoint, CConnman& connman)
2015-08-07 05:07:40 +02:00
{
if(!pnode) return;
CNetMsgMaker msgMaker(pnode->GetSendVersion());
LOCK(cs);
2015-08-07 05:07:40 +02:00
CService addrSquashed = Params().AllowMultiplePorts() ? (CService)pnode->addr : CService(pnode->addr, 0);
auto it1 = mWeAskedForMasternodeListEntry.find(outpoint);
if (it1 != mWeAskedForMasternodeListEntry.end()) {
auto it2 = it1->second.find(addrSquashed);
if (it2 != it1->second.end()) {
if (GetTime() < it2->second) {
// we've asked recently, should not repeat too often or we could get banned
return;
}
// we asked this node for this outpoint but it's ok to ask again already
LogPrintf("CMasternodeMan::AskForMN -- Asking same peer %s for missing masternode entry again: %s\n", addrSquashed.ToString(), outpoint.ToStringShort());
} else {
// we already asked for this outpoint but not this node
LogPrintf("CMasternodeMan::AskForMN -- Asking new peer %s for missing masternode entry: %s\n", addrSquashed.ToString(), outpoint.ToStringShort());
}
} else {
// we never asked any node for this outpoint
LogPrintf("CMasternodeMan::AskForMN -- Asking peer %s for missing masternode entry for the first time: %s\n", addrSquashed.ToString(), outpoint.ToStringShort());
}
mWeAskedForMasternodeListEntry[outpoint][addrSquashed] = GetTime() + DSEG_UPDATE_SECONDS;
2015-08-07 05:07:40 +02:00
if (pnode->GetSendVersion() == 70208) {
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSEG, CTxIn(outpoint)));
} else {
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSEG, outpoint));
}
}
bool CMasternodeMan::AllowMixing(const COutPoint &outpoint)
{
LOCK(cs);
CMasternode* pmn = Find(outpoint);
if (!pmn) {
return false;
}
nDsqCount++;
pmn->nLastDsq = nDsqCount;
pmn->fAllowMixingTx = true;
return true;
}
bool CMasternodeMan::DisallowMixing(const COutPoint &outpoint)
{
LOCK(cs);
CMasternode* pmn = Find(outpoint);
if (!pmn) {
return false;
}
pmn->fAllowMixingTx = false;
return true;
2015-08-07 05:07:40 +02:00
}
bool CMasternodeMan::PoSeBan(const COutPoint &outpoint)
{
LOCK(cs);
CMasternode* pmn = Find(outpoint);
if (!pmn) {
return false;
}
pmn->PoSeBan();
return true;
}
void CMasternodeMan::Check()
{
LOCK2(cs_main, cs);
LogPrint("masternode", "CMasternodeMan::Check -- nLastSentinelPingTime=%d, IsSentinelPingActive()=%d\n", nLastSentinelPingTime, IsSentinelPingActive());
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
for (auto& mnpair : mapMasternodes) {
// NOTE: internally it checks only every MASTERNODE_CHECK_SECONDS seconds
// since the last time, so expect some MNs to skip this
mnpair.second.Check();
2015-06-24 18:41:03 +02:00
}
}
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
void CMasternodeMan::CheckAndRemove(CConnman& connman)
{
if(!masternodeSync.IsMasternodeListSynced()) return;
LogPrintf("CMasternodeMan::CheckAndRemove\n");
{
// Need LOCK2 here to ensure consistent locking order because code below locks cs_main
// in CheckMnbAndUpdateMasternodeList()
LOCK2(cs_main, cs);
Check();
2015-07-30 15:44:18 +02:00
// Remove spent masternodes, prepare structures and make requests to reasure the state of inactive ones
rank_pair_vec_t vecMasternodeRanks;
// ask for up to MNB_RECOVERY_MAX_ASK_ENTRIES masternode entries at a time
int nAskForMnbRecovery = MNB_RECOVERY_MAX_ASK_ENTRIES;
std::map<COutPoint, CMasternode>::iterator it = mapMasternodes.begin();
while (it != mapMasternodes.end()) {
CMasternodeBroadcast mnb = CMasternodeBroadcast(it->second);
uint256 hash = mnb.GetHash();
// If collateral was spent ...
if (it->second.IsOutpointSpent()) {
LogPrint("masternode", "CMasternodeMan::CheckAndRemove -- Removing Masternode: %s addr=%s %i now\n", it->second.GetStateString(), it->second.addr.ToString(), size() - 1);
// erase all of the broadcasts we've seen from this txin, ...
mapSeenMasternodeBroadcast.erase(hash);
mWeAskedForMasternodeListEntry.erase(it->first);
// and finally remove it from the list
it->second.FlagGovernanceItemsAsDirty();
mapMasternodes.erase(it++);
fMasternodesRemoved = true;
} else {
bool fAsk = (nAskForMnbRecovery > 0) &&
masternodeSync.IsSynced() &&
it->second.IsNewStartRequired() &&
A pack of small fixes (#1992) * Make sure gobject collateral was mined `CGovernanceObject::IsCollateralValid()` would still fail for non-mined collateral later trying to check confirmations * Fix powLimit for mainnet/testnet That's a legacy thing, slightly rising it to match the actual bit-shifted value has no effect because real values are already lower. Also clarify values for all networks in comments. * Check for script addresses in CSuperblock::ParsePaymentSchedule() Sentinel should already be downvoting such triggers if they would exist, no need to store/relay them. * Do not process already known valid vote twice in CGovernanceObject::ProcessVote() This should be handled by `CGovernanceManager::ProcessVote()` but imo it's better to have this at the `CGovernanceObject::ProcessVote()` level as well. * Make sure CGovernanceObjectVoteFile::AddVote() never adds/updates already known votes The way `CGovernanceObjectVoteFile::AddVote()` is used (i.e. wrapped in `CGovernanceObjectVoteFile::HasVote()` condition) it's already the case. Hoever nothing would guarantee consistency if it would be used elsewhere without such wrapper, so it's better to have similar check inside. * Do not even try mnb recovery when -connect is set `CConnman::ThreadOpenMasternodeConnections()` thread won't even start when `-connect` is set, so no need to ask for recovery, there is nothing that is going to be able to process such request. * No need for SIGHASH_ANYONECANPAY in PS collateral signature Collateral is just a normal tx created and signed by each participant individually, there is no need for special sig types. * Release semMasternodeOutbound in CConnman::Interrupt() Re-align Dash code with Bitcoin.
2018-03-19 14:08:32 +01:00
!IsMnbRecoveryRequested(hash) &&
!IsArgSet("-connect");
if(fAsk) {
// this mn is in a non-recoverable state and we haven't asked other nodes yet
std::set<CService> setRequested;
// calulate only once and only when it's needed
if(vecMasternodeRanks.empty()) {
int nRandomBlockHeight = GetRandInt(nCachedBlockHeight);
GetMasternodeRanks(vecMasternodeRanks, nRandomBlockHeight);
}
bool fAskedForMnbRecovery = false;
// ask first MNB_RECOVERY_QUORUM_TOTAL masternodes we can connect to and we haven't asked recently
for(int i = 0; setRequested.size() < MNB_RECOVERY_QUORUM_TOTAL && i < (int)vecMasternodeRanks.size(); i++) {
// avoid banning
if(mWeAskedForMasternodeListEntry.count(it->first) && mWeAskedForMasternodeListEntry[it->first].count(vecMasternodeRanks[i].second.addr)) continue;
// didn't ask recently, ok to ask now
CService addr = vecMasternodeRanks[i].second.addr;
setRequested.insert(addr);
listScheduledMnbRequestConnections.push_back(std::make_pair(addr, hash));
fAskedForMnbRecovery = true;
}
if(fAskedForMnbRecovery) {
LogPrint("masternode", "CMasternodeMan::CheckAndRemove -- Recovery initiated, masternode=%s\n", it->first.ToStringShort());
nAskForMnbRecovery--;
}
// wait for mnb recovery replies for MNB_RECOVERY_WAIT_SECONDS seconds
mMnbRecoveryRequests[hash] = std::make_pair(GetTime() + MNB_RECOVERY_WAIT_SECONDS, setRequested);
}
++it;
}
}
// proces replies for MASTERNODE_NEW_START_REQUIRED masternodes
LogPrint("masternode", "CMasternodeMan::CheckAndRemove -- mMnbRecoveryGoodReplies size=%d\n", (int)mMnbRecoveryGoodReplies.size());
std::map<uint256, std::vector<CMasternodeBroadcast> >::iterator itMnbReplies = mMnbRecoveryGoodReplies.begin();
while(itMnbReplies != mMnbRecoveryGoodReplies.end()){
if(mMnbRecoveryRequests[itMnbReplies->first].first < GetTime()) {
// all nodes we asked should have replied now
if(itMnbReplies->second.size() >= MNB_RECOVERY_QUORUM_REQUIRED) {
// majority of nodes we asked agrees that this mn doesn't require new mnb, reprocess one of new mnbs
LogPrint("masternode", "CMasternodeMan::CheckAndRemove -- reprocessing mnb, masternode=%s\n", itMnbReplies->second[0].outpoint.ToStringShort());
// mapSeenMasternodeBroadcast.erase(itMnbReplies->first);
int nDos;
itMnbReplies->second[0].fRecovery = true;
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
CheckMnbAndUpdateMasternodeList(NULL, itMnbReplies->second[0], nDos, connman);
}
LogPrint("masternode", "CMasternodeMan::CheckAndRemove -- removing mnb recovery reply, masternode=%s, size=%d\n", itMnbReplies->second[0].outpoint.ToStringShort(), (int)itMnbReplies->second.size());
mMnbRecoveryGoodReplies.erase(itMnbReplies++);
} else {
++itMnbReplies;
}
}
}
{
// no need for cm_main below
LOCK(cs);
auto itMnbRequest = mMnbRecoveryRequests.begin();
while(itMnbRequest != mMnbRecoveryRequests.end()){
// Allow this mnb to be re-verified again after MNB_RECOVERY_RETRY_SECONDS seconds
// if mn is still in MASTERNODE_NEW_START_REQUIRED state.
if(GetTime() - itMnbRequest->second.first > MNB_RECOVERY_RETRY_SECONDS) {
mMnbRecoveryRequests.erase(itMnbRequest++);
} else {
++itMnbRequest;
}
}
// check who's asked for the Masternode list
auto it1 = mAskedUsForMasternodeList.begin();
while(it1 != mAskedUsForMasternodeList.end()){
if((*it1).second < GetTime()) {
mAskedUsForMasternodeList.erase(it1++);
} else {
++it1;
}
}
// check who we asked for the Masternode list
it1 = mWeAskedForMasternodeList.begin();
while(it1 != mWeAskedForMasternodeList.end()){
if((*it1).second < GetTime()){
mWeAskedForMasternodeList.erase(it1++);
} else {
++it1;
}
}
// check which Masternodes we've asked for
auto it2 = mWeAskedForMasternodeListEntry.begin();
while(it2 != mWeAskedForMasternodeListEntry.end()){
auto it3 = it2->second.begin();
while(it3 != it2->second.end()){
if(it3->second < GetTime()){
it2->second.erase(it3++);
} else {
++it3;
}
}
if(it2->second.empty()) {
mWeAskedForMasternodeListEntry.erase(it2++);
} else {
++it2;
}
}
2015-08-29 05:25:55 +02:00
auto it3 = mWeAskedForVerification.begin();
while(it3 != mWeAskedForVerification.end()){
if(it3->second.nBlockHeight < nCachedBlockHeight - MAX_POSE_BLOCKS) {
mWeAskedForVerification.erase(it3++);
} else {
++it3;
}
}
// NOTE: do not expire mapSeenMasternodeBroadcast entries here, clean them on mnb updates!
// remove expired mapSeenMasternodePing
std::map<uint256, CMasternodePing>::iterator it4 = mapSeenMasternodePing.begin();
while(it4 != mapSeenMasternodePing.end()){
if((*it4).second.IsExpired()) {
LogPrint("masternode", "CMasternodeMan::CheckAndRemove -- Removing expired Masternode ping: hash=%s\n", (*it4).second.GetHash().ToString());
mapSeenMasternodePing.erase(it4++);
} else {
++it4;
}
}
// remove expired mapSeenMasternodeVerification
std::map<uint256, CMasternodeVerification>::iterator itv2 = mapSeenMasternodeVerification.begin();
while(itv2 != mapSeenMasternodeVerification.end()){
if((*itv2).second.nBlockHeight < nCachedBlockHeight - MAX_POSE_BLOCKS){
LogPrint("masternode", "CMasternodeMan::CheckAndRemove -- Removing expired Masternode verification: hash=%s\n", (*itv2).first.ToString());
mapSeenMasternodeVerification.erase(itv2++);
} else {
++itv2;
}
}
LogPrintf("CMasternodeMan::CheckAndRemove -- %s\n", ToString());
2016-10-20 23:11:30 +02:00
}
if(fMasternodesRemoved) {
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
NotifyMasternodeUpdates(connman);
}
}
2015-03-01 01:04:17 +01:00
void CMasternodeMan::Clear()
{
LOCK(cs);
mapMasternodes.clear();
2015-03-01 01:04:17 +01:00
mAskedUsForMasternodeList.clear();
mWeAskedForMasternodeList.clear();
mWeAskedForMasternodeListEntry.clear();
mapSeenMasternodeBroadcast.clear();
mapSeenMasternodePing.clear();
2015-03-06 18:25:48 +01:00
nDsqCount = 0;
nLastSentinelPingTime = 0;
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
}
int CMasternodeMan::CountMasternodes(int nProtocolVersion)
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
{
LOCK(cs);
int nCount = 0;
nProtocolVersion = nProtocolVersion == -1 ? mnpayments.GetMinMasternodePaymentsProto() : nProtocolVersion;
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
for (const auto& mnpair : mapMasternodes) {
if(mnpair.second.nProtocolVersion < nProtocolVersion) continue;
nCount++;
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
}
return nCount;
2015-03-01 01:04:17 +01:00
}
int CMasternodeMan::CountEnabled(int nProtocolVersion)
{
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
LOCK(cs);
int nCount = 0;
nProtocolVersion = nProtocolVersion == -1 ? mnpayments.GetMinMasternodePaymentsProto() : nProtocolVersion;
for (const auto& mnpair : mapMasternodes) {
if(mnpair.second.nProtocolVersion < nProtocolVersion || !mnpair.second.IsEnabled()) continue;
nCount++;
}
return nCount;
}
/* Only IPv4 masternodes are allowed in 12.1, saving this for later
int CMasternodeMan::CountByIP(int nNetworkType)
{
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
LOCK(cs);
int nNodeCount = 0;
for (const auto& mnpair : mapMasternodes)
if ((nNetworkType == NET_IPV4 && mnpair.second.addr.IsIPv4()) ||
(nNetworkType == NET_TOR && mnpair.second.addr.IsTor()) ||
(nNetworkType == NET_IPV6 && mnpair.second.addr.IsIPv6())) {
nNodeCount++;
}
return nNodeCount;
}
*/
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
void CMasternodeMan::DsegUpdate(CNode* pnode, CConnman& connman)
{
CNetMsgMaker msgMaker(pnode->GetSendVersion());
LOCK(cs);
CService addrSquashed = Params().AllowMultiplePorts() ? (CService)pnode->addr : CService(pnode->addr, 0);
if(Params().NetworkIDString() == CBaseChainParams::MAIN) {
if(!(pnode->addr.IsRFC1918() || pnode->addr.IsLocal())) {
auto it = mWeAskedForMasternodeList.find(addrSquashed);
if(it != mWeAskedForMasternodeList.end() && GetTime() < (*it).second) {
LogPrintf("CMasternodeMan::DsegUpdate -- we already asked %s for the list; skipping...\n", addrSquashed.ToString());
return;
2015-07-02 17:07:30 +02:00
}
}
}
if (pnode->GetSendVersion() == 70208) {
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSEG, CTxIn()));
} else {
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSEG, COutPoint()));
}
2016-10-20 23:11:30 +02:00
int64_t askAgain = GetTime() + DSEG_UPDATE_SECONDS;
mWeAskedForMasternodeList[addrSquashed] = askAgain;
LogPrint("masternode", "CMasternodeMan::DsegUpdate -- asked %s for the list\n", pnode->addr.ToString());
}
CMasternode* CMasternodeMan::Find(const COutPoint &outpoint)
{
LOCK(cs);
auto it = mapMasternodes.find(outpoint);
return it == mapMasternodes.end() ? NULL : &(it->second);
}
bool CMasternodeMan::Get(const COutPoint& outpoint, CMasternode& masternodeRet)
{
// Theses mutexes are recursive so double locking by the same thread is safe.
LOCK(cs);
auto it = mapMasternodes.find(outpoint);
if (it == mapMasternodes.end()) {
return false;
}
masternodeRet = it->second;
return true;
}
bool CMasternodeMan::GetMasternodeInfo(const COutPoint& outpoint, masternode_info_t& mnInfoRet)
{
LOCK(cs);
auto it = mapMasternodes.find(outpoint);
if (it == mapMasternodes.end()) {
return false;
}
mnInfoRet = it->second.GetInfo();
return true;
}
bool CMasternodeMan::GetMasternodeInfo(const CPubKey& pubKeyMasternode, masternode_info_t& mnInfoRet)
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
{
LOCK(cs);
for (const auto& mnpair : mapMasternodes) {
if (mnpair.second.pubKeyMasternode == pubKeyMasternode) {
mnInfoRet = mnpair.second.GetInfo();
return true;
}
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
}
return false;
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
}
bool CMasternodeMan::GetMasternodeInfo(const CScript& payee, masternode_info_t& mnInfoRet)
{
LOCK(cs);
for (const auto& mnpair : mapMasternodes) {
CScript scriptCollateralAddress = GetScriptForDestination(mnpair.second.pubKeyCollateralAddress.GetID());
if (scriptCollateralAddress == payee) {
mnInfoRet = mnpair.second.GetInfo();
return true;
}
}
return false;
}
bool CMasternodeMan::Has(const COutPoint& outpoint)
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
{
LOCK(cs);
return mapMasternodes.find(outpoint) != mapMasternodes.end();
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
}
//
// Deterministically select the oldest/best masternode to pay on the network
//
bool CMasternodeMan::GetNextMasternodeInQueueForPayment(bool fFilterSigTime, int& nCountRet, masternode_info_t& mnInfoRet)
{
return GetNextMasternodeInQueueForPayment(nCachedBlockHeight, fFilterSigTime, nCountRet, mnInfoRet);
}
bool CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight, bool fFilterSigTime, int& nCountRet, masternode_info_t& mnInfoRet)
{
mnInfoRet = masternode_info_t();
nCountRet = 0;
if (!masternodeSync.IsWinnersListSynced()) {
// without winner list we can't reliably find the next winner anyway
return false;
}
// Need LOCK2 here to ensure consistent locking order because the GetBlockHash call below locks cs_main
LOCK2(cs_main,cs);
std::vector<std::pair<int, const CMasternode*> > vecMasternodeLastPaid;
/*
Make a vector with all of the last paid times
*/
int nMnCount = CountMasternodes();
for (const auto& mnpair : mapMasternodes) {
if(!mnpair.second.IsValidForPayment()) continue;
2017-07-03 15:14:07 +02:00
//check protocol version
if(mnpair.second.nProtocolVersion < mnpayments.GetMinMasternodePaymentsProto()) continue;
//it's in the list (up to 8 entries ahead of current block to allow propagation) -- so let's skip it
if(mnpayments.IsScheduled(mnpair.second, nBlockHeight)) continue;
//it's too new, wait for a cycle
if(fFilterSigTime && mnpair.second.sigTime + (nMnCount*2.6*60) > GetAdjustedTime()) continue;
//make sure it has at least as many confirmations as there are masternodes
if(GetUTXOConfirmations(mnpair.first) < nMnCount) continue;
vecMasternodeLastPaid.push_back(std::make_pair(mnpair.second.GetLastPaidBlock(), &mnpair.second));
}
nCountRet = (int)vecMasternodeLastPaid.size();
//when the network is in the process of upgrading, don't penalize nodes that recently restarted
if(fFilterSigTime && nCountRet < nMnCount/3)
return GetNextMasternodeInQueueForPayment(nBlockHeight, false, nCountRet, mnInfoRet);
// Sort them low to high
sort(vecMasternodeLastPaid.begin(), vecMasternodeLastPaid.end(), CompareLastPaidBlock());
uint256 blockHash;
if(!GetBlockHash(blockHash, nBlockHeight - 101)) {
LogPrintf("CMasternode::GetNextMasternodeInQueueForPayment -- ERROR: GetBlockHash() failed at nBlockHeight %d\n", nBlockHeight - 101);
return false;
}
// Look at 1/10 of the oldest nodes (by last payment), calculate their scores and pay the best one
// -- This doesn't look at who is being paid in the +8-10 blocks, allowing for double payments very rarely
// -- 1/100 payments should be a double payment on mainnet - (1/(3000/10))*2
// -- (chance per block * chances before IsScheduled will fire)
int nTenthNetwork = nMnCount/10;
int nCountTenth = 0;
arith_uint256 nHighest = 0;
const CMasternode *pBestMasternode = NULL;
for (const auto& s : vecMasternodeLastPaid) {
arith_uint256 nScore = s.second->CalculateScore(blockHash);
if(nScore > nHighest){
nHighest = nScore;
pBestMasternode = s.second;
}
nCountTenth++;
if(nCountTenth >= nTenthNetwork) break;
}
if (pBestMasternode) {
mnInfoRet = pBestMasternode->GetInfo();
}
return mnInfoRet.fInfoValid;
}
masternode_info_t CMasternodeMan::FindRandomNotInVec(const std::vector<COutPoint> &vecToExclude, int nProtocolVersion)
{
LOCK(cs);
nProtocolVersion = nProtocolVersion == -1 ? mnpayments.GetMinMasternodePaymentsProto() : nProtocolVersion;
int nCountEnabled = CountEnabled(nProtocolVersion);
int nCountNotExcluded = nCountEnabled - vecToExclude.size();
LogPrintf("CMasternodeMan::FindRandomNotInVec -- %d enabled masternodes, %d masternodes to choose from\n", nCountEnabled, nCountNotExcluded);
if(nCountNotExcluded < 1) return masternode_info_t();
// fill a vector of pointers
std::vector<const CMasternode*> vpMasternodesShuffled;
for (const auto& mnpair : mapMasternodes) {
vpMasternodesShuffled.push_back(&mnpair.second);
}
FastRandomContext insecure_rand;
// shuffle pointers
std::random_shuffle(vpMasternodesShuffled.begin(), vpMasternodesShuffled.end(), insecure_rand);
bool fExclude;
// loop through
for (const auto& pmn : vpMasternodesShuffled) {
if(pmn->nProtocolVersion < nProtocolVersion || !pmn->IsEnabled()) continue;
fExclude = false;
for (const auto& outpointToExclude : vecToExclude) {
if(pmn->outpoint == outpointToExclude) {
fExclude = true;
break;
}
}
if(fExclude) continue;
// found the one not in vecToExclude
LogPrint("masternode", "CMasternodeMan::FindRandomNotInVec -- found, masternode=%s\n", pmn->outpoint.ToStringShort());
return pmn->GetInfo();
}
LogPrint("masternode", "CMasternodeMan::FindRandomNotInVec -- failed\n");
return masternode_info_t();
}
bool CMasternodeMan::GetMasternodeScores(const uint256& nBlockHash, CMasternodeMan::score_pair_vec_t& vecMasternodeScoresRet, int nMinProtocol)
{
vecMasternodeScoresRet.clear();
if (!masternodeSync.IsMasternodeListSynced())
return false;
2015-03-23 13:59:22 +01:00
AssertLockHeld(cs);
if (mapMasternodes.empty())
return false;
// calculate scores
for (const auto& mnpair : mapMasternodes) {
if (mnpair.second.nProtocolVersion >= nMinProtocol) {
vecMasternodeScoresRet.push_back(std::make_pair(mnpair.second.CalculateScore(nBlockHash), &mnpair.second));
}
}
sort(vecMasternodeScoresRet.rbegin(), vecMasternodeScoresRet.rend(), CompareScoreMN());
return !vecMasternodeScoresRet.empty();
}
bool CMasternodeMan::GetMasternodeRank(const COutPoint& outpoint, int& nRankRet, int nBlockHeight, int nMinProtocol)
{
nRankRet = -1;
if (!masternodeSync.IsMasternodeListSynced())
return false;
// make sure we know about this block
uint256 nBlockHash = uint256();
if (!GetBlockHash(nBlockHash, nBlockHeight)) {
LogPrintf("CMasternodeMan::%s -- ERROR: GetBlockHash() failed at nBlockHeight %d\n", __func__, nBlockHeight);
return false;
}
LOCK(cs);
score_pair_vec_t vecMasternodeScores;
if (!GetMasternodeScores(nBlockHash, vecMasternodeScores, nMinProtocol))
return false;
int nRank = 0;
for (const auto& scorePair : vecMasternodeScores) {
nRank++;
if(scorePair.second->outpoint == outpoint) {
nRankRet = nRank;
return true;
}
}
return false;
}
bool CMasternodeMan::GetMasternodeRanks(CMasternodeMan::rank_pair_vec_t& vecMasternodeRanksRet, int nBlockHeight, int nMinProtocol)
{
vecMasternodeRanksRet.clear();
if (!masternodeSync.IsMasternodeListSynced())
return false;
// make sure we know about this block
uint256 nBlockHash = uint256();
if (!GetBlockHash(nBlockHash, nBlockHeight)) {
LogPrintf("CMasternodeMan::%s -- ERROR: GetBlockHash() failed at nBlockHeight %d\n", __func__, nBlockHeight);
return false;
}
LOCK(cs);
score_pair_vec_t vecMasternodeScores;
if (!GetMasternodeScores(nBlockHash, vecMasternodeScores, nMinProtocol))
return false;
int nRank = 0;
for (const auto& scorePair : vecMasternodeScores) {
nRank++;
vecMasternodeRanksRet.push_back(std::make_pair(nRank, *scorePair.second));
}
return true;
}
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
void CMasternodeMan::ProcessMasternodeConnections(CConnman& connman)
2015-03-02 00:09:33 +01:00
{
//we don't care about this for regtest
if(Params().NetworkIDString() == CBaseChainParams::REGTEST) return;
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
connman.ForEachNode(CConnman::AllNodes, [](CNode* pnode) {
#ifdef ENABLE_WALLET
if(pnode->fMasternode && !privateSendClient.IsMixingMasternode(pnode)) {
#else
if(pnode->fMasternode) {
#endif // ENABLE_WALLET
LogPrintf("Closing Masternode connection: peer=%d, addr=%s\n", pnode->id, pnode->addr.ToString());
pnode->fDisconnect = true;
2015-03-02 00:09:33 +01:00
}
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537) * net: move CBanDB and CAddrDB out of net.h/cpp This will eventually solve a circular dependency * net: Create CConnman to encapsulate p2p connections * net: Move socket binding into CConnman * net: move OpenNetworkConnection into CConnman * net: move ban and addrman functions into CConnman * net: Add oneshot functions to CConnman * net: move added node functions to CConnman * net: Add most functions needed for vNodes to CConnman * net: handle nodesignals in CConnman * net: Pass CConnection to wallet rather than using the global * net: Add rpc error for missing/disabled p2p functionality * net: Pass CConnman around as needed * gui: add NodeID to the peer table * net: create generic functor accessors and move vNodes to CConnman * net: move whitelist functions into CConnman * net: move nLastNodeId to CConnman * net: move nLocalHostNonce to CConnman This behavior seems to have been quite racy and broken. Move nLocalHostNonce into CNode, and check received nonces against all non-fully-connected nodes. If there's a match, assume we've connected to ourself. * net: move messageHandlerCondition to CConnman * net: move send/recv statistics to CConnman * net: move SendBufferSize/ReceiveFloodSize to CConnman * net: move nLocalServices/nRelevantServices to CConnman These are in-turn passed to CNode at connection time. This allows us to offer different services to different peers (or test the effects of doing so). * net: move semOutbound and semMasternodeOutbound to CConnman * net: SocketSendData returns written size * net: move max/max-outbound to CConnman * net: Pass best block known height into CConnman CConnman then passes the current best height into CNode at creation time. This way CConnman/CNode have no dependency on main for height, and the signals only move in one direction. This also helps to prevent identity leakage a tiny bit. Before this change, an attacker could theoretically make 2 connections on different interfaces. They would connect fully on one, and only establish the initial connection on the other. Once they receive a new block, they would relay it to your first connection, and immediately commence the version handshake on the second. Since the new block height is reflected immediately, they could attempt to learn whether the two connections were correlated. This is, of course, incredibly unlikely to work due to the small timings involved and receipt from other senders. But it doesn't hurt to lock-in nBestHeight at the time of connection, rather than letting the remote choose the time. * net: pass CClientUIInterface into CConnman * net: Drop StartNode/StopNode and use CConnman directly * net: Introduce CConnection::Options to avoid passing so many params * net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options * net: move vNodesDisconnected into CConnman * Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting * Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead * net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
});
2015-03-02 00:09:33 +01:00
}
std::pair<CService, std::set<uint256> > CMasternodeMan::PopScheduledMnbRequestConnection()
{
LOCK(cs);
if(listScheduledMnbRequestConnections.empty()) {
return std::make_pair(CService(), std::set<uint256>());
}
std::set<uint256> setResult;
listScheduledMnbRequestConnections.sort();
std::pair<CService, uint256> pairFront = listScheduledMnbRequestConnections.front();
// squash hashes from requests with the same CService as the first one into setResult
std::list< std::pair<CService, uint256> >::iterator it = listScheduledMnbRequestConnections.begin();
while(it != listScheduledMnbRequestConnections.end()) {
if(pairFront.first == it->first) {
setResult.insert(it->second);
it = listScheduledMnbRequestConnections.erase(it);
} else {
// since list is sorted now, we can be sure that there is no more hashes left
// to ask for from this addr
break;
}
}
return std::make_pair(pairFront.first, setResult);
}
void CMasternodeMan::ProcessPendingMnbRequests(CConnman& connman)
{
std::pair<CService, std::set<uint256> > p = PopScheduledMnbRequestConnection();
if (!(p.first == CService() || p.second.empty())) {
if (connman.IsMasternodeOrDisconnectRequested(p.first)) return;
mapPendingMNB.insert(std::make_pair(p.first, std::make_pair(GetTime(), p.second)));
connman.AddPendingMasternode(p.first);
}
std::map<CService, std::pair<int64_t, std::set<uint256> > >::iterator itPendingMNB = mapPendingMNB.begin();
while (itPendingMNB != mapPendingMNB.end()) {
bool fDone = connman.ForNode(itPendingMNB->first, [&](CNode* pnode) {
// compile request vector
std::vector<CInv> vToFetch;
std::set<uint256>& setHashes = itPendingMNB->second.second;
std::set<uint256>::iterator it = setHashes.begin();
while(it != setHashes.end()) {
if(*it != uint256()) {
vToFetch.push_back(CInv(MSG_MASTERNODE_ANNOUNCE, *it));
LogPrint("masternode", "-- asking for mnb %s from addr=%s\n", it->ToString(), pnode->addr.ToString());
}
++it;
}
// ask for data
CNetMsgMaker msgMaker(pnode->GetSendVersion());
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::GETDATA, vToFetch));
return true;
});
int64_t nTimeAdded = itPendingMNB->second.first;
if (fDone || (GetTime() - nTimeAdded > 15)) {
if (!fDone) {
LogPrint("masternode", "CMasternodeMan::%s -- failed to connect to %s\n", __func__, itPendingMNB->first.ToString());
}
mapPendingMNB.erase(itPendingMNB++);
} else {
++itPendingMNB;
}
}
LogPrint("masternode", "%s -- mapPendingMNB size: %d\n", __func__, mapPendingMNB.size());
}
void CMasternodeMan::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman)
{
if(fLiteMode) return; // disable all Dash specific functionality
if (strCommand == NetMsgType::MNANNOUNCE) { //Masternode Broadcast
CMasternodeBroadcast mnb;
vRecv >> mnb;
pfrom->setAskFor.erase(mnb.GetHash());
if(!masternodeSync.IsBlockchainSynced()) return;
LogPrint("masternode", "MNANNOUNCE -- Masternode announce, masternode=%s\n", mnb.outpoint.ToStringShort());
int nDos = 0;
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
if (CheckMnbAndUpdateMasternodeList(pfrom, mnb, nDos, connman)) {
// use announced Masternode as a peer
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
connman.AddNewAddress(CAddress(mnb.addr, NODE_NETWORK), pfrom->addr, 2*60*60);
} else if(nDos > 0) {
LOCK(cs_main);
Misbehaving(pfrom->GetId(), nDos);
}
if(fMasternodesAdded) {
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
NotifyMasternodeUpdates(connman);
}
} else if (strCommand == NetMsgType::MNPING) { //Masternode Ping
CMasternodePing mnp;
vRecv >> mnp;
uint256 nHash = mnp.GetHash();
pfrom->setAskFor.erase(nHash);
if(!masternodeSync.IsBlockchainSynced()) return;
LogPrint("masternode", "MNPING -- Masternode ping, masternode=%s\n", mnp.masternodeOutpoint.ToStringShort());
// Need LOCK2 here to ensure consistent locking order because the CheckAndUpdate call below locks cs_main
LOCK2(cs_main, cs);
2016-10-30 20:40:30 +01:00
if(mapSeenMasternodePing.count(nHash)) return; //seen
mapSeenMasternodePing.insert(std::make_pair(nHash, mnp));
LogPrint("masternode", "MNPING -- Masternode ping, masternode=%s new\n", mnp.masternodeOutpoint.ToStringShort());
// see if we have this Masternode
CMasternode* pmn = Find(mnp.masternodeOutpoint);
if(pmn && mnp.fSentinelIsCurrent)
UpdateLastSentinelPingTime();
// too late, new MNANNOUNCE is required
if(pmn && pmn->IsNewStartRequired()) return;
int nDos = 0;
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
if(mnp.CheckAndUpdate(pmn, false, nDos, connman)) return;
if(nDos > 0) {
2015-08-07 05:07:40 +02:00
// if anything significant failed, mark that node
Misbehaving(pfrom->GetId(), nDos);
} else if(pmn != NULL) {
// nothing significant failed, mn is a known one too
return;
}
2015-08-07 05:07:40 +02:00
// something significant is broken or mn is unknown,
// we might have to ask for a masternode entry once
AskForMN(pfrom, mnp.masternodeOutpoint, connman);
} else if (strCommand == NetMsgType::DSEG) { //Get Masternode list or specific entry
// Ignore such requests until we are fully synced.
// We could start processing this after masternode list is synced
// but this is a heavy one so it's better to finish sync first.
if (!masternodeSync.IsSynced()) return;
COutPoint masternodeOutpoint;
if (pfrom->nVersion == 70208) {
CTxIn vin;
vRecv >> vin;
masternodeOutpoint = vin.prevout;
} else {
vRecv >> masternodeOutpoint;
}
LogPrint("masternode", "DSEG -- Masternode list, masternode=%s\n", masternodeOutpoint.ToStringShort());
if(masternodeOutpoint.IsNull()) {
SyncAll(pfrom, connman);
} else {
SyncSingle(pfrom, masternodeOutpoint, connman);
}
2016-10-20 23:11:30 +02:00
} else if (strCommand == NetMsgType::MNVERIFY) { // Masternode Verify
// Need LOCK2 here to ensure consistent locking order because all functions below call GetBlockHash which locks cs_main
LOCK2(cs_main, cs);
2016-10-20 23:11:30 +02:00
CMasternodeVerification mnv;
vRecv >> mnv;
pfrom->setAskFor.erase(mnv.GetHash());
if(!masternodeSync.IsMasternodeListSynced()) return;
2016-10-20 23:11:30 +02:00
if(mnv.vchSig1.empty()) {
// CASE 1: someone asked me to verify myself /IP we are using/
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
SendVerifyReply(pfrom, mnv, connman);
2016-10-20 23:11:30 +02:00
} else if (mnv.vchSig2.empty()) {
// CASE 2: we _probably_ got verification we requested from some masternode
ProcessVerifyReply(pfrom, mnv);
} else {
// CASE 3: we _probably_ got verification broadcast signed by some masternode which verified another one
ProcessVerifyBroadcast(pfrom, mnv);
}
}
}
void CMasternodeMan::SyncSingle(CNode* pnode, const COutPoint& outpoint, CConnman& connman)
{
// do not provide any data until our node is synced
if (!masternodeSync.IsSynced()) return;
LOCK(cs);
auto it = mapMasternodes.find(outpoint);
if(it != mapMasternodes.end()) {
if (it->second.addr.IsRFC1918() || it->second.addr.IsLocal()) return; // do not send local network masternode
// NOTE: send masternode regardless of its current state, the other node will need it to verify old votes.
LogPrint("masternode", "CMasternodeMan::%s -- Sending Masternode entry: masternode=%s addr=%s\n", __func__, outpoint.ToStringShort(), it->second.addr.ToString());
PushDsegInvs(pnode, it->second);
LogPrintf("CMasternodeMan::%s -- Sent 1 Masternode inv to peer=%d\n", __func__, pnode->id);
}
}
void CMasternodeMan::SyncAll(CNode* pnode, CConnman& connman)
{
// do not provide any data until our node is synced
if (!masternodeSync.IsSynced()) return;
// local network
bool isLocal = (pnode->addr.IsRFC1918() || pnode->addr.IsLocal());
CService addrSquashed = Params().AllowMultiplePorts() ? (CService)pnode->addr : CService(pnode->addr, 0);
// should only ask for this once
if(!isLocal && Params().NetworkIDString() == CBaseChainParams::MAIN) {
LOCK2(cs_main, cs);
auto it = mAskedUsForMasternodeList.find(addrSquashed);
if (it != mAskedUsForMasternodeList.end() && it->second > GetTime()) {
Misbehaving(pnode->GetId(), 34);
LogPrintf("CMasternodeMan::%s -- peer already asked me for the list, peer=%d\n", __func__, pnode->id);
return;
}
int64_t askAgain = GetTime() + DSEG_UPDATE_SECONDS;
mAskedUsForMasternodeList[addrSquashed] = askAgain;
}
int nInvCount = 0;
LOCK(cs);
for (const auto& mnpair : mapMasternodes) {
if (mnpair.second.addr.IsRFC1918() || mnpair.second.addr.IsLocal()) continue; // do not send local network masternode
// NOTE: send masternode regardless of its current state, the other node will need it to verify old votes.
LogPrint("masternode", "CMasternodeMan::%s -- Sending Masternode entry: masternode=%s addr=%s\n", __func__, mnpair.first.ToStringShort(), mnpair.second.addr.ToString());
PushDsegInvs(pnode, mnpair.second);
nInvCount++;
}
connman.PushMessage(pnode, CNetMsgMaker(pnode->GetSendVersion()).Make(NetMsgType::SYNCSTATUSCOUNT, MASTERNODE_SYNC_LIST, nInvCount));
LogPrintf("CMasternodeMan::%s -- Sent %d Masternode invs to peer=%d\n", __func__, nInvCount, pnode->id);
}
void CMasternodeMan::PushDsegInvs(CNode* pnode, const CMasternode& mn)
{
AssertLockHeld(cs);
CMasternodeBroadcast mnb(mn);
CMasternodePing mnp = mnb.lastPing;
uint256 hashMNB = mnb.GetHash();
uint256 hashMNP = mnp.GetHash();
pnode->PushInventory(CInv(MSG_MASTERNODE_ANNOUNCE, hashMNB));
pnode->PushInventory(CInv(MSG_MASTERNODE_PING, hashMNP));
mapSeenMasternodeBroadcast.insert(std::make_pair(hashMNB, std::make_pair(GetTime(), mnb)));
mapSeenMasternodePing.insert(std::make_pair(hashMNP, mnp));
}
// Verification of masternodes via unique direct requests.
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
void CMasternodeMan::DoFullVerificationStep(CConnman& connman)
2016-10-20 23:11:30 +02:00
{
if(activeMasternode.outpoint.IsNull()) return;
if(!masternodeSync.IsSynced()) return;
2016-10-20 23:11:30 +02:00
rank_pair_vec_t vecMasternodeRanks;
GetMasternodeRanks(vecMasternodeRanks, nCachedBlockHeight - 1, MIN_POSE_PROTO_VERSION);
2016-10-20 23:11:30 +02:00
LOCK(cs);
2016-10-20 23:11:30 +02:00
int nCount = 0;
int nMyRank = -1;
int nRanksTotal = (int)vecMasternodeRanks.size();
// send verify requests only if we are in top MAX_POSE_RANK
rank_pair_vec_t::iterator it = vecMasternodeRanks.begin();
2016-10-20 23:11:30 +02:00
while(it != vecMasternodeRanks.end()) {
if(it->first > MAX_POSE_RANK) {
LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Must be in top %d to send verify request\n",
(int)MAX_POSE_RANK);
return;
}
if(it->second.outpoint == activeMasternode.outpoint) {
2016-10-20 23:11:30 +02:00
nMyRank = it->first;
LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Found self at rank %d/%d, verifying up to %d masternodes\n",
nMyRank, nRanksTotal, (int)MAX_POSE_CONNECTIONS);
2016-10-20 23:11:30 +02:00
break;
}
++it;
}
// edge case: list is too short and this masternode is not enabled
if(nMyRank == -1) return;
// send verify requests to up to MAX_POSE_CONNECTIONS masternodes
// starting from MAX_POSE_RANK + nMyRank and using MAX_POSE_CONNECTIONS as a step
int nOffset = MAX_POSE_RANK + nMyRank - 1;
2016-10-20 23:11:30 +02:00
if(nOffset >= (int)vecMasternodeRanks.size()) return;
std::vector<const CMasternode*> vSortedByAddr;
for (const auto& mnpair : mapMasternodes) {
vSortedByAddr.push_back(&mnpair.second);
2016-10-20 23:11:30 +02:00
}
sort(vSortedByAddr.begin(), vSortedByAddr.end(), CompareByAddr());
it = vecMasternodeRanks.begin() + nOffset;
while(it != vecMasternodeRanks.end()) {
if(it->second.IsPoSeVerified() || it->second.IsPoSeBanned()) {
LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Already %s%s%s masternode %s address %s, skipping...\n",
it->second.IsPoSeVerified() ? "verified" : "",
it->second.IsPoSeVerified() && it->second.IsPoSeBanned() ? " and " : "",
it->second.IsPoSeBanned() ? "banned" : "",
it->second.outpoint.ToStringShort(), it->second.addr.ToString());
nOffset += MAX_POSE_CONNECTIONS;
if(nOffset >= (int)vecMasternodeRanks.size()) break;
it += MAX_POSE_CONNECTIONS;
2016-10-20 23:11:30 +02:00
continue;
}
LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Verifying masternode %s rank %d/%d address %s\n",
it->second.outpoint.ToStringShort(), it->first, nRanksTotal, it->second.addr.ToString());
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
if(SendVerifyRequest(CAddress(it->second.addr, NODE_NETWORK), vSortedByAddr, connman)) {
2016-10-20 23:11:30 +02:00
nCount++;
if(nCount >= MAX_POSE_CONNECTIONS) break;
2016-10-20 23:11:30 +02:00
}
nOffset += MAX_POSE_CONNECTIONS;
if(nOffset >= (int)vecMasternodeRanks.size()) break;
it += MAX_POSE_CONNECTIONS;
2016-10-20 23:11:30 +02:00
}
LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Sent verification requests to %d masternodes\n", nCount);
}
// This function tries to find masternodes with the same addr,
// find a verified one and ban all the other. If there are many nodes
// with the same addr but none of them is verified yet, then none of them are banned.
// It could take many times to run this before most of the duplicate nodes are banned.
2016-10-20 23:11:30 +02:00
void CMasternodeMan::CheckSameAddr()
{
if(!masternodeSync.IsSynced() || mapMasternodes.empty()) return;
2016-10-20 23:11:30 +02:00
std::vector<CMasternode*> vBan;
std::vector<CMasternode*> vSortedByAddr;
{
LOCK(cs);
CMasternode* pprevMasternode = NULL;
CMasternode* pverifiedMasternode = NULL;
for (auto& mnpair : mapMasternodes) {
vSortedByAddr.push_back(&mnpair.second);
2016-10-20 23:11:30 +02:00
}
sort(vSortedByAddr.begin(), vSortedByAddr.end(), CompareByAddr());
for (const auto& pmn : vSortedByAddr) {
2016-10-20 23:11:30 +02:00
// check only (pre)enabled masternodes
if(!pmn->IsEnabled() && !pmn->IsPreEnabled()) continue;
// initial step
if(!pprevMasternode) {
pprevMasternode = pmn;
pverifiedMasternode = pmn->IsPoSeVerified() ? pmn : NULL;
continue;
}
// second+ step
if(pmn->addr == pprevMasternode->addr) {
if(pverifiedMasternode) {
// another masternode with the same ip is verified, ban this one
vBan.push_back(pmn);
} else if(pmn->IsPoSeVerified()) {
// this masternode with the same ip is verified, ban previous one
vBan.push_back(pprevMasternode);
// and keep a reference to be able to ban following masternodes with the same ip
pverifiedMasternode = pmn;
}
} else {
pverifiedMasternode = pmn->IsPoSeVerified() ? pmn : NULL;
}
pprevMasternode = pmn;
}
}
// ban duplicates
for (auto& pmn : vBan) {
LogPrintf("CMasternodeMan::CheckSameAddr -- increasing PoSe ban score for masternode %s\n", pmn->outpoint.ToStringShort());
pmn->IncreasePoSeBanScore();
2016-10-20 23:11:30 +02:00
}
}
bool CMasternodeMan::SendVerifyRequest(const CAddress& addr, const std::vector<const CMasternode*>& vSortedByAddr, CConnman& connman)
2016-10-20 23:11:30 +02:00
{
if(netfulfilledman.HasFulfilledRequest(addr, strprintf("%s", NetMsgType::MNVERIFY)+"-request")) {
// we already asked for verification, not a good idea to do this too often, skip it
LogPrint("masternode", "CMasternodeMan::SendVerifyRequest -- too many requests, skipping... addr=%s\n", addr.ToString());
return false;
}
if (connman.IsMasternodeOrDisconnectRequested(addr)) return false;
connman.AddPendingMasternode(addr);
// use random nonce, store it and require node to reply with correct one later
CMasternodeVerification mnv(addr, GetRandInt(999999), nCachedBlockHeight - 1);
LOCK(cs_mapPendingMNV);
mapPendingMNV.insert(std::make_pair(addr, std::make_pair(GetTime(), mnv)));
LogPrintf("CMasternodeMan::SendVerifyRequest -- verifying node using nonce %d addr=%s\n", mnv.nonce, addr.ToString());
return true;
2016-10-20 23:11:30 +02:00
}
void CMasternodeMan::ProcessPendingMnvRequests(CConnman& connman)
{
LOCK(cs_mapPendingMNV);
std::map<CService, std::pair<int64_t, CMasternodeVerification> >::iterator itPendingMNV = mapPendingMNV.begin();
while (itPendingMNV != mapPendingMNV.end()) {
bool fDone = connman.ForNode(itPendingMNV->first, [&](CNode* pnode) {
netfulfilledman.AddFulfilledRequest(pnode->addr, strprintf("%s", NetMsgType::MNVERIFY)+"-request");
// use random nonce, store it and require node to reply with correct one later
mWeAskedForVerification[pnode->addr] = itPendingMNV->second.second;
LogPrint("masternode", "-- verifying node using nonce %d addr=%s\n", itPendingMNV->second.second.nonce, pnode->addr.ToString());
CNetMsgMaker msgMaker(pnode->GetSendVersion()); // TODO this gives a warning about version not being set (we should wait for VERSION exchange)
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::MNVERIFY, itPendingMNV->second.second));
return true;
});
int64_t nTimeAdded = itPendingMNV->second.first;
if (fDone || (GetTime() - nTimeAdded > 15)) {
if (!fDone) {
LogPrint("masternode", "CMasternodeMan::%s -- failed to connect to %s\n", __func__, itPendingMNV->first.ToString());
}
mapPendingMNV.erase(itPendingMNV++);
} else {
++itPendingMNV;
}
}
LogPrint("masternode", "%s -- mapPendingMNV size: %d\n", __func__, mapPendingMNV.size());
}
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
void CMasternodeMan::SendVerifyReply(CNode* pnode, CMasternodeVerification& mnv, CConnman& connman)
2016-10-20 23:11:30 +02:00
{
AssertLockHeld(cs_main);
2016-10-20 23:11:30 +02:00
// only masternodes can sign this, why would someone ask regular node?
if(!fMasternodeMode) {
2016-10-20 23:11:30 +02:00
// do not ban, malicious node might be using my IP
// and trying to confuse the node which tries to verify it
return;
}
if(netfulfilledman.HasFulfilledRequest(pnode->addr, strprintf("%s", NetMsgType::MNVERIFY)+"-reply")) {
// peer should not ask us that often
LogPrintf("MasternodeMan::SendVerifyReply -- ERROR: peer already asked me recently, peer=%d\n", pnode->id);
Misbehaving(pnode->id, 20);
return;
}
uint256 blockHash;
if(!GetBlockHash(blockHash, mnv.nBlockHeight)) {
LogPrintf("MasternodeMan::SendVerifyReply -- can't get block hash for unknown block height %d, peer=%d\n", mnv.nBlockHeight, pnode->id);
return;
}
std::string strError;
2016-10-20 23:11:30 +02:00
if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
uint256 hash = mnv.GetSignatureHash1(blockHash);
2016-10-20 23:11:30 +02:00
if(!CHashSigner::SignHash(hash, activeMasternode.keyMasternode, mnv.vchSig1)) {
LogPrintf("CMasternodeMan::SendVerifyReply -- SignHash() failed\n");
return;
}
2016-10-20 23:11:30 +02:00
if (!CHashSigner::VerifyHash(hash, activeMasternode.pubKeyMasternode, mnv.vchSig1, strError)) {
LogPrintf("CMasternodeMan::SendVerifyReply -- VerifyHash() failed, error: %s\n", strError);
return;
}
} else {
std::string strMessage = strprintf("%s%d%s", activeMasternode.service.ToString(false), mnv.nonce, blockHash.ToString());
if(!CMessageSigner::SignMessage(strMessage, mnv.vchSig1, activeMasternode.keyMasternode)) {
LogPrintf("MasternodeMan::SendVerifyReply -- SignMessage() failed\n");
return;
}
if(!CMessageSigner::VerifyMessage(activeMasternode.pubKeyMasternode, mnv.vchSig1, strMessage, strError)) {
LogPrintf("MasternodeMan::SendVerifyReply -- VerifyMessage() failed, error: %s\n", strError);
return;
}
2016-10-20 23:11:30 +02:00
}
CNetMsgMaker msgMaker(pnode->GetSendVersion());
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::MNVERIFY, mnv));
2016-10-20 23:11:30 +02:00
netfulfilledman.AddFulfilledRequest(pnode->addr, strprintf("%s", NetMsgType::MNVERIFY)+"-reply");
}
void CMasternodeMan::ProcessVerifyReply(CNode* pnode, CMasternodeVerification& mnv)
{
AssertLockHeld(cs_main);
2016-10-20 23:11:30 +02:00
std::string strError;
// did we even ask for it? if that's the case we should have matching fulfilled request
if(!netfulfilledman.HasFulfilledRequest(pnode->addr, strprintf("%s", NetMsgType::MNVERIFY)+"-request")) {
LogPrintf("CMasternodeMan::ProcessVerifyReply -- ERROR: we didn't ask for verification of %s, peer=%d\n", pnode->addr.ToString(), pnode->id);
Misbehaving(pnode->id, 20);
return;
}
// Received nonce for a known address must match the one we sent
if(mWeAskedForVerification[pnode->addr].nonce != mnv.nonce) {
LogPrintf("CMasternodeMan::ProcessVerifyReply -- ERROR: wrong nounce: requested=%d, received=%d, peer=%d\n",
mWeAskedForVerification[pnode->addr].nonce, mnv.nonce, pnode->id);
Misbehaving(pnode->id, 20);
return;
}
// Received nBlockHeight for a known address must match the one we sent
if(mWeAskedForVerification[pnode->addr].nBlockHeight != mnv.nBlockHeight) {
LogPrintf("CMasternodeMan::ProcessVerifyReply -- ERROR: wrong nBlockHeight: requested=%d, received=%d, peer=%d\n",
mWeAskedForVerification[pnode->addr].nBlockHeight, mnv.nBlockHeight, pnode->id);
Misbehaving(pnode->id, 20);
return;
}
uint256 blockHash;
if(!GetBlockHash(blockHash, mnv.nBlockHeight)) {
// this shouldn't happen...
LogPrintf("MasternodeMan::ProcessVerifyReply -- can't get block hash for unknown block height %d, peer=%d\n", mnv.nBlockHeight, pnode->id);
return;
}
// we already verified this address, why node is spamming?
if(netfulfilledman.HasFulfilledRequest(pnode->addr, strprintf("%s", NetMsgType::MNVERIFY)+"-done")) {
LogPrintf("CMasternodeMan::ProcessVerifyReply -- ERROR: already verified %s recently\n", pnode->addr.ToString());
Misbehaving(pnode->id, 20);
return;
}
{
LOCK(cs);
CMasternode* prealMasternode = NULL;
std::vector<CMasternode*> vpMasternodesToBan;
uint256 hash1 = mnv.GetSignatureHash1(blockHash);
2016-10-20 23:11:30 +02:00
std::string strMessage1 = strprintf("%s%d%s", pnode->addr.ToString(false), mnv.nonce, blockHash.ToString());
for (auto& mnpair : mapMasternodes) {
if(CAddress(mnpair.second.addr, NODE_NETWORK) == pnode->addr) {
bool fFound = false;
if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
fFound = CHashSigner::VerifyHash(hash1, mnpair.second.pubKeyMasternode, mnv.vchSig1, strError);
// we don't care about mnv with signature in old format
} else {
fFound = CMessageSigner::VerifyMessage(mnpair.second.pubKeyMasternode, mnv.vchSig1, strMessage1, strError);
}
if (fFound) {
2016-10-20 23:11:30 +02:00
// found it!
prealMasternode = &mnpair.second;
if(!mnpair.second.IsPoSeVerified()) {
mnpair.second.DecreasePoSeBanScore();
2016-10-20 23:11:30 +02:00
}
netfulfilledman.AddFulfilledRequest(pnode->addr, strprintf("%s", NetMsgType::MNVERIFY)+"-done");
// we can only broadcast it if we are an activated masternode
if(activeMasternode.outpoint.IsNull()) continue;
2016-10-20 23:11:30 +02:00
// update ...
mnv.addr = mnpair.second.addr;
mnv.masternodeOutpoint1 = mnpair.second.outpoint;
mnv.masternodeOutpoint2 = activeMasternode.outpoint;
2016-10-20 23:11:30 +02:00
// ... and sign it
std::string strError;
if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
uint256 hash2 = mnv.GetSignatureHash2(blockHash);
if(!CHashSigner::SignHash(hash2, activeMasternode.keyMasternode, mnv.vchSig2)) {
LogPrintf("MasternodeMan::ProcessVerifyReply -- SignHash() failed\n");
return;
}
if(!CHashSigner::VerifyHash(hash2, activeMasternode.pubKeyMasternode, mnv.vchSig2, strError)) {
LogPrintf("MasternodeMan::ProcessVerifyReply -- VerifyHash() failed, error: %s\n", strError);
return;
}
} else {
std::string strMessage2 = strprintf("%s%d%s%s%s", mnv.addr.ToString(false), mnv.nonce, blockHash.ToString(),
mnv.masternodeOutpoint1.ToStringShort(), mnv.masternodeOutpoint2.ToStringShort());
if(!CMessageSigner::SignMessage(strMessage2, mnv.vchSig2, activeMasternode.keyMasternode)) {
LogPrintf("MasternodeMan::ProcessVerifyReply -- SignMessage() failed\n");
return;
}
if(!CMessageSigner::VerifyMessage(activeMasternode.pubKeyMasternode, mnv.vchSig2, strMessage2, strError)) {
LogPrintf("MasternodeMan::ProcessVerifyReply -- VerifyMessage() failed, error: %s\n", strError);
return;
}
2016-10-20 23:11:30 +02:00
}
mWeAskedForVerification[pnode->addr] = mnv;
mapSeenMasternodeVerification.insert(std::make_pair(mnv.GetHash(), mnv));
2016-10-20 23:11:30 +02:00
mnv.Relay();
} else {
vpMasternodesToBan.push_back(&mnpair.second);
2016-10-20 23:11:30 +02:00
}
}
}
// no real masternode found?...
if(!prealMasternode) {
// this should never be the case normally,
// only if someone is trying to game the system in some way or smth like that
LogPrintf("CMasternodeMan::ProcessVerifyReply -- ERROR: no real masternode found for addr %s\n", pnode->addr.ToString());
Misbehaving(pnode->id, 20);
return;
}
LogPrintf("CMasternodeMan::ProcessVerifyReply -- verified real masternode %s for addr %s\n",
prealMasternode->outpoint.ToStringShort(), pnode->addr.ToString());
2016-10-20 23:11:30 +02:00
// increase ban score for everyone else
for (const auto& pmn : vpMasternodesToBan) {
pmn->IncreasePoSeBanScore();
LogPrint("masternode", "CMasternodeMan::ProcessVerifyReply -- increased PoSe ban score for %s addr %s, new score %d\n",
prealMasternode->outpoint.ToStringShort(), pnode->addr.ToString(), pmn->nPoSeBanScore);
2016-10-20 23:11:30 +02:00
}
if(!vpMasternodesToBan.empty())
LogPrintf("CMasternodeMan::ProcessVerifyReply -- PoSe score increased for %d fake masternodes, addr %s\n",
(int)vpMasternodesToBan.size(), pnode->addr.ToString());
2016-10-20 23:11:30 +02:00
}
}
void CMasternodeMan::ProcessVerifyBroadcast(CNode* pnode, const CMasternodeVerification& mnv)
{
AssertLockHeld(cs_main);
2016-10-20 23:11:30 +02:00
std::string strError;
if(mapSeenMasternodeVerification.find(mnv.GetHash()) != mapSeenMasternodeVerification.end()) {
// we already have one
return;
}
mapSeenMasternodeVerification[mnv.GetHash()] = mnv;
// we don't care about history
if(mnv.nBlockHeight < nCachedBlockHeight - MAX_POSE_BLOCKS) {
LogPrint("masternode", "CMasternodeMan::ProcessVerifyBroadcast -- Outdated: current block %d, verification block %d, peer=%d\n",
nCachedBlockHeight, mnv.nBlockHeight, pnode->id);
2016-10-20 23:11:30 +02:00
return;
}
if(mnv.masternodeOutpoint1 == mnv.masternodeOutpoint2) {
LogPrint("masternode", "CMasternodeMan::ProcessVerifyBroadcast -- ERROR: same outpoints %s, peer=%d\n",
mnv.masternodeOutpoint1.ToStringShort(), pnode->id);
2016-10-20 23:11:30 +02:00
// that was NOT a good idea to cheat and verify itself,
// ban the node we received such message from
Misbehaving(pnode->id, 100);
return;
}
uint256 blockHash;
if(!GetBlockHash(blockHash, mnv.nBlockHeight)) {
// this shouldn't happen...
LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- Can't get block hash for unknown block height %d, peer=%d\n", mnv.nBlockHeight, pnode->id);
2016-10-20 23:11:30 +02:00
return;
}
int nRank;
if (!GetMasternodeRank(mnv.masternodeOutpoint2, nRank, mnv.nBlockHeight, MIN_POSE_PROTO_VERSION)) {
LogPrint("masternode", "CMasternodeMan::ProcessVerifyBroadcast -- Can't calculate rank for masternode %s\n",
mnv.masternodeOutpoint2.ToStringShort());
return;
}
if(nRank > MAX_POSE_RANK) {
LogPrint("masternode", "CMasternodeMan::ProcessVerifyBroadcast -- Masternode %s is not in top %d, current rank %d, peer=%d\n",
mnv.masternodeOutpoint2.ToStringShort(), (int)MAX_POSE_RANK, nRank, pnode->id);
2016-10-20 23:11:30 +02:00
return;
}
{
LOCK(cs);
CMasternode* pmn1 = Find(mnv.masternodeOutpoint1);
2016-10-20 23:11:30 +02:00
if(!pmn1) {
LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- can't find masternode1 %s\n", mnv.masternodeOutpoint1.ToStringShort());
2016-10-20 23:11:30 +02:00
return;
}
CMasternode* pmn2 = Find(mnv.masternodeOutpoint2);
2016-10-20 23:11:30 +02:00
if(!pmn2) {
LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- can't find masternode2 %s\n", mnv.masternodeOutpoint2.ToStringShort());
2016-10-20 23:11:30 +02:00
return;
}
if(pmn1->addr != mnv.addr) {
LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- addr %s does not match %s\n", mnv.addr.ToString(), pmn1->addr.ToString());
2016-10-20 23:11:30 +02:00
return;
}
if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
uint256 hash1 = mnv.GetSignatureHash1(blockHash);
uint256 hash2 = mnv.GetSignatureHash2(blockHash);
2016-10-20 23:11:30 +02:00
if(!CHashSigner::VerifyHash(hash1, pmn1->pubKeyMasternode, mnv.vchSig1, strError)) {
LogPrintf("MasternodeMan::ProcessVerifyBroadcast -- VerifyHash() failed, error: %s\n", strError);
return;
}
if(!CHashSigner::VerifyHash(hash2, pmn2->pubKeyMasternode, mnv.vchSig2, strError)) {
LogPrintf("MasternodeMan::ProcessVerifyBroadcast -- VerifyHash() failed, error: %s\n", strError);
return;
}
} else {
std::string strMessage1 = strprintf("%s%d%s", mnv.addr.ToString(false), mnv.nonce, blockHash.ToString());
std::string strMessage2 = strprintf("%s%d%s%s%s", mnv.addr.ToString(false), mnv.nonce, blockHash.ToString(),
mnv.masternodeOutpoint1.ToStringShort(), mnv.masternodeOutpoint2.ToStringShort());
if(!CMessageSigner::VerifyMessage(pmn1->pubKeyMasternode, mnv.vchSig1, strMessage1, strError)) {
LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- VerifyMessage() for masternode1 failed, error: %s\n", strError);
return;
}
if(!CMessageSigner::VerifyMessage(pmn2->pubKeyMasternode, mnv.vchSig2, strMessage2, strError)) {
LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- VerifyMessage() for masternode2 failed, error: %s\n", strError);
return;
}
2016-10-20 23:11:30 +02:00
}
if(!pmn1->IsPoSeVerified()) {
pmn1->DecreasePoSeBanScore();
2016-10-20 23:11:30 +02:00
}
mnv.Relay();
LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- verified masternode %s for addr %s\n",
pmn1->outpoint.ToStringShort(), pmn1->addr.ToString());
2016-10-20 23:11:30 +02:00
// increase ban score for everyone else with the same addr
int nCount = 0;
for (auto& mnpair : mapMasternodes) {
if(mnpair.second.addr != mnv.addr || mnpair.first == mnv.masternodeOutpoint1) continue;
mnpair.second.IncreasePoSeBanScore();
2016-10-20 23:11:30 +02:00
nCount++;
LogPrint("masternode", "CMasternodeMan::ProcessVerifyBroadcast -- increased PoSe ban score for %s addr %s, new score %d\n",
mnpair.first.ToStringShort(), mnpair.second.addr.ToString(), mnpair.second.nPoSeBanScore);
2016-10-20 23:11:30 +02:00
}
if(nCount)
LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- PoSe score increased for %d fake masternodes, addr %s\n",
nCount, pmn1->addr.ToString());
}
}
std::string CMasternodeMan::ToString() const
{
std::ostringstream info;
info << "Masternodes: " << (int)mapMasternodes.size() <<
2015-03-05 09:10:15 +01:00
", peers who asked us for Masternode list: " << (int)mAskedUsForMasternodeList.size() <<
", peers we asked for Masternode list: " << (int)mWeAskedForMasternodeList.size() <<
2015-03-06 18:25:48 +01:00
", entries in Masternode list we asked for: " << (int)mWeAskedForMasternodeListEntry.size() <<
", nDsqCount: " << (int)nDsqCount;
return info.str();
}
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
bool CMasternodeMan::CheckMnbAndUpdateMasternodeList(CNode* pfrom, CMasternodeBroadcast mnb, int& nDos, CConnman& connman)
2016-10-20 23:11:30 +02:00
{
// Need to lock cs_main here to ensure consistent locking order because the SimpleCheck call below locks cs_main
LOCK(cs_main);
2016-10-20 23:11:30 +02:00
{
LOCK(cs);
nDos = 0;
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s\n", mnb.outpoint.ToStringShort());
uint256 hash = mnb.GetHash();
if(mapSeenMasternodeBroadcast.count(hash) && !mnb.fRecovery) { //seen
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s seen\n", mnb.outpoint.ToStringShort());
// less then 2 pings left before this MN goes into non-recoverable state, bump sync timeout
if(GetTime() - mapSeenMasternodeBroadcast[hash].first > MASTERNODE_NEW_START_REQUIRED_SECONDS - MASTERNODE_MIN_MNP_SECONDS * 2) {
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s seen update\n", mnb.outpoint.ToStringShort());
mapSeenMasternodeBroadcast[hash].first = GetTime();
masternodeSync.BumpAssetLastTime("CMasternodeMan::CheckMnbAndUpdateMasternodeList - seen");
}
// did we ask this node for it?
if(pfrom && IsMnbRecoveryRequested(hash) && GetTime() < mMnbRecoveryRequests[hash].first) {
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- mnb=%s seen request\n", hash.ToString());
if(mMnbRecoveryRequests[hash].second.count(pfrom->addr)) {
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- mnb=%s seen request, addr=%s\n", hash.ToString(), pfrom->addr.ToString());
// do not allow node to send same mnb multiple times in recovery mode
mMnbRecoveryRequests[hash].second.erase(pfrom->addr);
// does it have newer lastPing?
if(mnb.lastPing.sigTime > mapSeenMasternodeBroadcast[hash].second.lastPing.sigTime) {
// simulate Check
CMasternode mnTemp = CMasternode(mnb);
mnTemp.Check();
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- mnb=%s seen request, addr=%s, better lastPing: %d min ago, projected mn state: %s\n", hash.ToString(), pfrom->addr.ToString(), (GetAdjustedTime() - mnb.lastPing.sigTime)/60, mnTemp.GetStateString());
if(mnTemp.IsValidStateForAutoStart(mnTemp.nActiveState)) {
// this node thinks it's a good one
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s seen good\n", mnb.outpoint.ToStringShort());
mMnbRecoveryGoodReplies[hash].push_back(mnb);
}
}
}
}
return true;
}
mapSeenMasternodeBroadcast.insert(std::make_pair(hash, std::make_pair(GetTime(), mnb)));
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s new\n", mnb.outpoint.ToStringShort());
if(!mnb.SimpleCheck(nDos)) {
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- SimpleCheck() failed, masternode=%s\n", mnb.outpoint.ToStringShort());
2016-10-20 23:11:30 +02:00
return false;
}
// search Masternode list
CMasternode* pmn = Find(mnb.outpoint);
if(pmn) {
CMasternodeBroadcast mnbOld = mapSeenMasternodeBroadcast[CMasternodeBroadcast(*pmn).GetHash()].second;
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
if(!mnb.Update(pmn, nDos, connman)) {
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- Update() failed, masternode=%s\n", mnb.outpoint.ToStringShort());
return false;
}
if(hash != mnbOld.GetHash()) {
mapSeenMasternodeBroadcast.erase(mnbOld.GetHash());
}
return true;
}
}
if(mnb.CheckOutpoint(nDos)) {
Add(mnb);
masternodeSync.BumpAssetLastTime("CMasternodeMan::CheckMnbAndUpdateMasternodeList - new");
// if it matches our Masternode privkey...
if(fMasternodeMode && mnb.pubKeyMasternode == activeMasternode.pubKeyMasternode) {
mnb.nPoSeBanScore = -MASTERNODE_POSE_BAN_MAX_SCORE;
if(mnb.nProtocolVersion == PROTOCOL_VERSION) {
// ... and PROTOCOL_VERSION, then we've been remotely activated ...
LogPrintf("CMasternodeMan::CheckMnbAndUpdateMasternodeList -- Got NEW Masternode entry: masternode=%s sigTime=%lld addr=%s\n",
mnb.outpoint.ToStringShort(), mnb.sigTime, mnb.addr.ToString());
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
activeMasternode.ManageState(connman);
} else {
// ... otherwise we need to reactivate our node, do not add it to the list and do not relay
// but also do not ban the node we get this message from
LogPrintf("CMasternodeMan::CheckMnbAndUpdateMasternodeList -- wrong PROTOCOL_VERSION, re-activate your MN: message nProtocolVersion=%d PROTOCOL_VERSION=%d\n", mnb.nProtocolVersion, PROTOCOL_VERSION);
return false;
2016-10-20 23:11:30 +02:00
}
}
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
mnb.Relay(connman);
} else {
LogPrintf("CMasternodeMan::CheckMnbAndUpdateMasternodeList -- Rejected Masternode entry: %s addr=%s\n", mnb.outpoint.ToStringShort(), mnb.addr.ToString());
return false;
}
return true;
}
void CMasternodeMan::UpdateLastPaid(const CBlockIndex* pindex)
2016-10-20 23:11:30 +02:00
{
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
LOCK(cs);
2016-10-20 23:11:30 +02:00
if(fLiteMode || !masternodeSync.IsWinnersListSynced() || mapMasternodes.empty()) return;
static int nLastRunBlockHeight = 0;
// Scan at least LAST_PAID_SCAN_BLOCKS but no more than mnpayments.GetStorageLimit()
int nMaxBlocksToScanBack = std::max(LAST_PAID_SCAN_BLOCKS, nCachedBlockHeight - nLastRunBlockHeight);
nMaxBlocksToScanBack = std::min(nMaxBlocksToScanBack, mnpayments.GetStorageLimit());
LogPrint("masternode", "CMasternodeMan::UpdateLastPaid -- nCachedBlockHeight=%d, nLastRunBlockHeight=%d, nMaxBlocksToScanBack=%d\n",
nCachedBlockHeight, nLastRunBlockHeight, nMaxBlocksToScanBack);
for (auto& mnpair : mapMasternodes) {
mnpair.second.UpdateLastPaid(pindex, nMaxBlocksToScanBack);
}
nLastRunBlockHeight = nCachedBlockHeight;
}
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
void CMasternodeMan::UpdateLastSentinelPingTime()
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
{
LOCK(cs);
nLastSentinelPingTime = GetTime();
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
}
bool CMasternodeMan::IsSentinelPingActive()
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
{
LOCK(cs);
// Check if any masternodes have voted recently, otherwise return false
return (GetTime() - nLastSentinelPingTime) <= MASTERNODE_SENTINEL_PING_MAX_SECONDS;
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
}
bool CMasternodeMan::AddGovernanceVote(const COutPoint& outpoint, uint256 nGovernanceObjectHash)
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
{
LOCK(cs);
CMasternode* pmn = Find(outpoint);
if(!pmn) {
return false;
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
}
pmn->AddGovernanceVote(nGovernanceObjectHash);
return true;
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
}
void CMasternodeMan::RemoveGovernanceObject(uint256 nGovernanceObjectHash)
{
LOCK(cs);
for(auto& mnpair : mapMasternodes) {
mnpair.second.RemoveGovernanceObject(nGovernanceObjectHash);
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
}
}
void CMasternodeMan::CheckMasternode(const CPubKey& pubKeyMasternode, bool fForce)
{
LOCK2(cs_main, cs);
for (auto& mnpair : mapMasternodes) {
if (mnpair.second.pubKeyMasternode == pubKeyMasternode) {
mnpair.second.Check(fForce);
return;
}
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
}
}
bool CMasternodeMan::IsMasternodePingedWithin(const COutPoint& outpoint, int nSeconds, int64_t nTimeToCheckAt)
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
{
LOCK(cs);
CMasternode* pmn = Find(outpoint);
return pmn ? pmn->IsPingedWithin(nSeconds, nTimeToCheckAt) : false;
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
}
void CMasternodeMan::SetMasternodeLastPing(const COutPoint& outpoint, const CMasternodePing& mnp)
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
{
LOCK(cs);
CMasternode* pmn = Find(outpoint);
if(!pmn) {
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
return;
}
pmn->lastPing = mnp;
if(mnp.fSentinelIsCurrent) {
UpdateLastSentinelPingTime();
}
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
mapSeenMasternodePing.insert(std::make_pair(mnp.GetHash(), mnp));
CMasternodeBroadcast mnb(*pmn);
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
uint256 hash = mnb.GetHash();
if(mapSeenMasternodeBroadcast.count(hash)) {
mapSeenMasternodeBroadcast[hash].second.lastPing = mnp;
V0.12.1.x sentinel watchdog pr (#1079) Squashed: * Replaced unsafe mnodeman.Find function with Get in governance-vote.cpp * Reject unparsable governance objects * Implemented sentinel watchdog objects (separated out from locking changes) * Added WATCHDOG support to rpcgovernance.cpp * Implemented WATCHDOG_EXPIRED state for masternodes * Added serialization of watchdog timestamps * Masternode fixes - Added version check to CMasternodeMan deserialization - Added several missing locking calls in CMasternodeMan * Fixed missing member initialization in CMasternode constructor and added more logging * Added MASTERNODE_WATCHDOG_MAX_SECONDS to governanceinfo * Added masternodewatchdogmaxseconds info to getgovernanceinfo help * Make masternodes remain in WATCHDOG_EXPIRED state unless removed or collateral expires * Allow watchdog object creation by WATCHDOG_EXPIRED MN * Fixed MN validation logic for governance object creation * Count total masternodes instead of enabled masternodes in masternode-sync * Transition out of WATCHDOG_EXPIRED state if the watchdog is inactive * Fixed IsWatchdogExpired bug * Fixed rate check for watchdog objects and no longer check MN state when validating governance objects * Applied PR #1061 patch * Ported locking changes from other branch * Require only 1 block between new watchdog objects * Accept pings for WATCHDOG_EXPIRED masternodes * Lock CmasternodeMan::cs in CmasternodeMan::ProcessMessage * Several governance changes - Fixed uninitialized value in CGovernancePayment class - Return an error on submission if any superblock payment cannot be parsed - Added logging more statements * Explicitly initialize all governance object members * Fix deadlock * Fixed non-threadsafe access to masternode in activemasternode.cpp * Revert added wallet lock * Changed CActiveMasternode so that watchdog expired nodes can still send pings * Modified CActiveMasternode to run pinger regardless of state when MN is in list * Added voter and time information to getvotes command * Improved CActiveMasternode state management * Implemented GetInfo functions for more efficient thread-safe access to masternode information * Added CActiveMasternode debug logging messages * Fixed initial type setting and error message for incorrect protocol version * Changes based on code review comments * Set active state for local mode
2016-10-17 20:54:28 +02:00
}
}
2016-10-20 23:11:30 +02:00
void CMasternodeMan::UpdatedBlockTip(const CBlockIndex *pindex)
{
nCachedBlockHeight = pindex->nHeight;
LogPrint("masternode", "CMasternodeMan::UpdatedBlockTip -- nCachedBlockHeight=%d\n", nCachedBlockHeight);
2016-10-20 23:11:30 +02:00
CheckSameAddr();
if(fMasternodeMode) {
2016-10-20 23:11:30 +02:00
// normal wallet does not need to update this every block, doing update on rpc call should be enough
UpdateLastPaid(pindex);
2016-10-20 23:11:30 +02:00
}
}
void CMasternodeMan::WarnMasternodeDaemonUpdates()
{
LOCK(cs);
static bool fWarned = false;
if (fWarned || !size() || !masternodeSync.IsMasternodeListSynced())
return;
int nUpdatedMasternodes{0};
for (const auto& mnpair : mapMasternodes) {
if (mnpair.second.lastPing.nDaemonVersion > CLIENT_VERSION) {
++nUpdatedMasternodes;
}
}
// Warn only when at least half of known masternodes already updated
if (nUpdatedMasternodes < size() / 2)
return;
std::string strWarning;
if (nUpdatedMasternodes != size()) {
strWarning = strprintf(_("Warning: At least %d of %d masternodes are running on a newer software version. Please check latest releases, you might need to update too."),
nUpdatedMasternodes, size());
} else {
// someone was postponing this update for way too long probably
strWarning = strprintf(_("Warning: Every masternode (out of %d known ones) is running on a newer software version. Please check latest releases, it's very likely that you missed a major/critical update."),
size());
}
// notify GetWarnings(), called by Qt and the JSON-RPC code to warn the user
SetMiscWarning(strWarning);
// trigger GUI update
uiInterface.NotifyAlertChanged(SerializeHash(strWarning), CT_NEW);
// trigger cmd-line notification
CAlert::Notify(strWarning);
fWarned = true;
}
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
void CMasternodeMan::NotifyMasternodeUpdates(CConnman& connman)
{
// Avoid double locking
bool fMasternodesAddedLocal = false;
bool fMasternodesRemovedLocal = false;
{
LOCK(cs);
fMasternodesAddedLocal = fMasternodesAdded;
fMasternodesRemovedLocal = fMasternodesRemoved;
}
if(fMasternodesAddedLocal) {
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
governance.CheckMasternodeOrphanObjects(connman);
governance.CheckMasternodeOrphanVotes(connman);
}
if(fMasternodesRemovedLocal) {
governance.UpdateCachesAndClean();
}
LOCK(cs);
fMasternodesAdded = false;
fMasternodesRemoved = false;
}