242 lines
9.4 KiB
C++
242 lines
9.4 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"
|
|
|
|
using namespace std;
|
|
|
|
class CMasternodeMan;
|
|
class CConnman;
|
|
|
|
extern CMasternodeMan mnodeman;
|
|
|
|
class CMasternodeMan
|
|
{
|
|
public:
|
|
typedef std::pair<arith_uint256, CMasternode*> score_pair_t;
|
|
typedef std::vector<score_pair_t> score_pair_vec_t;
|
|
typedef std::pair<int, 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 = 100;
|
|
|
|
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<CNetAddr, int64_t> mAskedUsForMasternodeList;
|
|
// who we asked for the Masternode list and the last time
|
|
std::map<CNetAddr, int64_t> mWeAskedForMasternodeList;
|
|
// which Masternodes we've asked for
|
|
std::map<COutPoint, std::map<CNetAddr, int64_t> > mWeAskedForMasternodeListEntry;
|
|
// who we asked for the masternode verification
|
|
std::map<CNetAddr, CMasternodeVerification> mWeAskedForVerification;
|
|
|
|
// these maps are used for masternode recovery from MASTERNODE_NEW_START_REQUIRED state
|
|
std::map<uint256, std::pair< int64_t, std::set<CNetAddr> > > mMnbRecoveryRequests;
|
|
std::map<uint256, std::vector<CMasternodeBroadcast> > mMnbRecoveryGoodReplies;
|
|
std::list< std::pair<CService, uint256> > listScheduledMnbRequestConnections;
|
|
|
|
/// 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 nLastWatchdogVoteTime;
|
|
|
|
friend class CMasternodeSync;
|
|
/// Find an entry
|
|
CMasternode* Find(const COutPoint& outpoint);
|
|
|
|
bool GetMasternodeScores(const uint256& nBlockHash, score_pair_vec_t& vecMasternodeScoresRet, int nMinProtocol = 0);
|
|
|
|
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, int nType, int nVersion) {
|
|
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(nLastWatchdogVoteTime);
|
|
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 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, bool fFilterScheduled, int& nCountRet, masternode_info_t& mnInfoRet);
|
|
/// Same as above but use current block height
|
|
bool GetNextMasternodeInQueueForPayment(bool fFilterSigTime, bool fFilterScheduled, 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);
|
|
bool GetMasternodeByRank(int nRank, masternode_info_t& mnInfoRet, int nBlockHeight = -1, int nMinProtocol = 0);
|
|
|
|
void ProcessMasternodeConnections(CConnman& connman);
|
|
std::pair<CService, std::set<uint256> > PopScheduledMnbRequestConnection();
|
|
|
|
void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv, CConnman& connman);
|
|
|
|
void DoFullVerificationStep(CConnman& connman);
|
|
void CheckSameAddr();
|
|
bool SendVerifyRequest(const CAddress& addr, const std::vector<CMasternode*>& vSortedByAddr, 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;
|
|
|
|
/// Update masternode list and maps using provided CMasternodeBroadcast
|
|
void UpdateMasternodeList(CMasternodeBroadcast mnb, CConnman& connman);
|
|
/// Perform complete check and only then update list and maps
|
|
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 IsWatchdogActive();
|
|
void UpdateWatchdogVoteTime(const COutPoint& outpoint, uint64_t nVoteTime = 0);
|
|
bool AddGovernanceVote(const COutPoint& outpoint, uint256 nGovernanceObjectHash);
|
|
void RemoveGovernanceObject(uint256 nGovernanceObjectHash);
|
|
|
|
void CheckMasternode(const CPubKey& pubKeyMasternode, 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);
|
|
|
|
/**
|
|
* 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);
|
|
|
|
};
|
|
|
|
#endif
|