neobytes/src/masternodeman.h
Alexander Block d946f21bd9 Masternode related refactorings in preparation of DIP3 (#2212)
* Split CActiveMasternode into CActiveMasternodeInfo and CLegacyActiveMasternodeManager

* Use CKeyID instead of CPubKey whenever possible in masternode code

* Rename activeMasternode to activeMasternodeInfo and make it a struct

* Rename pubKeyIDXXX to keyIDXXX

* Bump SERIALIZATION_VERSION_STRING

* Fix build error after rebase

* Fix compilation warning/error with clang
2018-08-11 22:55:56 +03:00

252 lines
9.7 KiB
C++

// Copyright (c) 2014-2017 The Dash Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef MASTERNODEMAN_H
#define MASTERNODEMAN_H
#include "masternode.h"
#include "sync.h"
class CMasternodeMan;
class CConnman;
extern CMasternodeMan mnodeman;
class CMasternodeMan
{
public:
typedef std::pair<arith_uint256, const CMasternode*> score_pair_t;
typedef std::vector<score_pair_t> score_pair_vec_t;
typedef std::pair<int, const CMasternode> rank_pair_t;
typedef std::vector<rank_pair_t> rank_pair_vec_t;
private:
static const std::string SERIALIZATION_VERSION_STRING;
static const int DSEG_UPDATE_SECONDS = 3 * 60 * 60;
static const int LAST_PAID_SCAN_BLOCKS;
static const int MIN_POSE_PROTO_VERSION = 70203;
static const int MAX_POSE_CONNECTIONS = 10;
static const int MAX_POSE_RANK = 10;
static const int MAX_POSE_BLOCKS = 10;
static const int MNB_RECOVERY_QUORUM_TOTAL = 10;
static const int MNB_RECOVERY_QUORUM_REQUIRED = 6;
static const int MNB_RECOVERY_MAX_ASK_ENTRIES = 10;
static const int MNB_RECOVERY_WAIT_SECONDS = 60;
static const int MNB_RECOVERY_RETRY_SECONDS = 3 * 60 * 60;
// critical section to protect the inner data structures
mutable CCriticalSection cs;
// Keep track of current block height
int nCachedBlockHeight;
// map to hold all MNs
std::map<COutPoint, CMasternode> mapMasternodes;
// who's asked for the Masternode list and the last time
std::map<CService, int64_t> mAskedUsForMasternodeList;
// who we asked for the Masternode list and the last time
std::map<CService, int64_t> mWeAskedForMasternodeList;
// which Masternodes we've asked for
std::map<COutPoint, std::map<CService, int64_t> > mWeAskedForMasternodeListEntry;
// who we asked for the masternode verification
std::map<CService, CMasternodeVerification> mWeAskedForVerification;
// these maps are used for masternode recovery from MASTERNODE_NEW_START_REQUIRED state
std::map<uint256, std::pair< int64_t, std::set<CService> > > mMnbRecoveryRequests;
std::map<uint256, std::vector<CMasternodeBroadcast> > mMnbRecoveryGoodReplies;
std::list< std::pair<CService, uint256> > listScheduledMnbRequestConnections;
std::map<CService, std::pair<int64_t, std::set<uint256> > > mapPendingMNB;
std::map<CService, std::pair<int64_t, CMasternodeVerification> > mapPendingMNV;
CCriticalSection cs_mapPendingMNV;
/// Set when masternodes are added, cleared when CGovernanceManager is notified
bool fMasternodesAdded;
/// Set when masternodes are removed, cleared when CGovernanceManager is notified
bool fMasternodesRemoved;
std::vector<uint256> vecDirtyGovernanceObjectHashes;
int64_t nLastSentinelPingTime;
friend class CMasternodeSync;
/// Find an entry
CMasternode* Find(const COutPoint& outpoint);
bool GetMasternodeScores(const uint256& nBlockHash, score_pair_vec_t& vecMasternodeScoresRet, int nMinProtocol = 0);
void SyncSingle(CNode* pnode, const COutPoint& outpoint, CConnman& connman);
void SyncAll(CNode* pnode, CConnman& connman);
void PushDsegInvs(CNode* pnode, const CMasternode& mn);
public:
// Keep track of all broadcasts I've seen
std::map<uint256, std::pair<int64_t, CMasternodeBroadcast> > mapSeenMasternodeBroadcast;
// Keep track of all pings I've seen
std::map<uint256, CMasternodePing> mapSeenMasternodePing;
// Keep track of all verifications I've seen
std::map<uint256, CMasternodeVerification> mapSeenMasternodeVerification;
// keep track of dsq count to prevent masternodes from gaming darksend queue
int64_t nDsqCount;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
LOCK(cs);
std::string strVersion;
if(ser_action.ForRead()) {
READWRITE(strVersion);
}
else {
strVersion = SERIALIZATION_VERSION_STRING;
READWRITE(strVersion);
}
READWRITE(mapMasternodes);
READWRITE(mAskedUsForMasternodeList);
READWRITE(mWeAskedForMasternodeList);
READWRITE(mWeAskedForMasternodeListEntry);
READWRITE(mMnbRecoveryRequests);
READWRITE(mMnbRecoveryGoodReplies);
READWRITE(nLastSentinelPingTime);
READWRITE(nDsqCount);
READWRITE(mapSeenMasternodeBroadcast);
READWRITE(mapSeenMasternodePing);
if(ser_action.ForRead() && (strVersion != SERIALIZATION_VERSION_STRING)) {
Clear();
}
}
CMasternodeMan();
/// Add an entry
bool Add(CMasternode &mn);
/// Ask (source) node for mnb
void AskForMN(CNode *pnode, const COutPoint& outpoint, CConnman& connman);
void AskForMnb(CNode *pnode, const uint256 &hash);
bool PoSeBan(const COutPoint &outpoint);
bool AllowMixing(const COutPoint &outpoint);
bool DisallowMixing(const COutPoint &outpoint);
/// Check all Masternodes
void Check();
/// Check all Masternodes and remove inactive
void CheckAndRemove(CConnman& connman);
/// This is dummy overload to be used for dumping/loading mncache.dat
void CheckAndRemove() {}
/// Clear Masternode vector
void Clear();
/// Count Masternodes filtered by nProtocolVersion.
/// Masternode nProtocolVersion should match or be above the one specified in param here.
int CountMasternodes(int nProtocolVersion = -1);
/// Count enabled Masternodes filtered by nProtocolVersion.
/// Masternode nProtocolVersion should match or be above the one specified in param here.
int CountEnabled(int nProtocolVersion = -1);
/// Count Masternodes by network type - NET_IPV4, NET_IPV6, NET_TOR
// int CountByIP(int nNetworkType);
void DsegUpdate(CNode* pnode, CConnman& connman);
/// Versions of Find that are safe to use from outside the class
bool Get(const COutPoint& outpoint, CMasternode& masternodeRet);
bool Has(const COutPoint& outpoint);
bool GetMasternodeInfo(const COutPoint& outpoint, masternode_info_t& mnInfoRet);
bool GetMasternodeInfo(const CKeyID& keyIDMasternode, masternode_info_t& mnInfoRet);
bool GetMasternodeInfo(const CPubKey& pubKeyMasternode, masternode_info_t& mnInfoRet);
bool GetMasternodeInfo(const CScript& payee, masternode_info_t& mnInfoRet);
/// Find an entry in the masternode list that is next to be paid
bool GetNextMasternodeInQueueForPayment(int nBlockHeight, bool fFilterSigTime, int& nCountRet, masternode_info_t& mnInfoRet);
/// Same as above but use current block height
bool GetNextMasternodeInQueueForPayment(bool fFilterSigTime, int& nCountRet, masternode_info_t& mnInfoRet);
/// Find a random entry
masternode_info_t FindRandomNotInVec(const std::vector<COutPoint> &vecToExclude, int nProtocolVersion = -1);
std::map<COutPoint, CMasternode> GetFullMasternodeMap() { return mapMasternodes; }
bool GetMasternodeRanks(rank_pair_vec_t& vecMasternodeRanksRet, int nBlockHeight = -1, int nMinProtocol = 0);
bool GetMasternodeRank(const COutPoint &outpoint, int& nRankRet, int nBlockHeight = -1, int nMinProtocol = 0);
void ProcessMasternodeConnections(CConnman& connman);
std::pair<CService, std::set<uint256> > PopScheduledMnbRequestConnection();
void ProcessPendingMnbRequests(CConnman& connman);
void ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman);
void DoFullVerificationStep(CConnman& connman);
void CheckSameAddr();
bool SendVerifyRequest(const CAddress& addr, const std::vector<const CMasternode*>& vSortedByAddr, CConnman& connman);
void ProcessPendingMnvRequests(CConnman& connman);
void SendVerifyReply(CNode* pnode, CMasternodeVerification& mnv, CConnman& connman);
void ProcessVerifyReply(CNode* pnode, CMasternodeVerification& mnv);
void ProcessVerifyBroadcast(CNode* pnode, const CMasternodeVerification& mnv);
/// Return the number of (unique) Masternodes
int size() { return mapMasternodes.size(); }
std::string ToString() const;
/// Perform complete check and only then update masternode list and maps using provided CMasternodeBroadcast
bool CheckMnbAndUpdateMasternodeList(CNode* pfrom, CMasternodeBroadcast mnb, int& nDos, CConnman& connman);
bool IsMnbRecoveryRequested(const uint256& hash) { return mMnbRecoveryRequests.count(hash); }
void UpdateLastPaid(const CBlockIndex* pindex);
void AddDirtyGovernanceObjectHash(const uint256& nHash)
{
LOCK(cs);
vecDirtyGovernanceObjectHashes.push_back(nHash);
}
std::vector<uint256> GetAndClearDirtyGovernanceObjectHashes()
{
LOCK(cs);
std::vector<uint256> vecTmp = vecDirtyGovernanceObjectHashes;
vecDirtyGovernanceObjectHashes.clear();
return vecTmp;;
}
bool IsSentinelPingActive();
void UpdateLastSentinelPingTime();
bool AddGovernanceVote(const COutPoint& outpoint, uint256 nGovernanceObjectHash);
void RemoveGovernanceObject(uint256 nGovernanceObjectHash);
void CheckMasternode(const CKeyID& keyIDMasternode, bool fForce);
bool IsMasternodePingedWithin(const COutPoint& outpoint, int nSeconds, int64_t nTimeToCheckAt = -1);
void SetMasternodeLastPing(const COutPoint& outpoint, const CMasternodePing& mnp);
void UpdatedBlockTip(const CBlockIndex *pindex);
void WarnMasternodeDaemonUpdates();
/**
* Called to notify CGovernanceManager that the masternode index has been updated.
* Must be called while not holding the CMasternodeMan::cs mutex
*/
void NotifyMasternodeUpdates(CConnman& connman);
void DoMaintenance(CConnman &connman);
};
#endif