dash/src/masternodeman.h
Alexander Block 35550a3f93
Add quorumModifierHash to instant send lock vote (#2505)
* Let GetMasternodeRank also return the block hash at the given height

* Add outpointConfirmedBlock to CTxLockVote and verify it

* Match order of parameters with member order

* Rename outpointConfirmedBlock to quorumModifierHash

* Add overload of GetMasternodeRank that does not return the block hash
2018-11-28 11:43:28 +01:00

256 lines
10 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 privatesend 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);
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() {}
void AddDeterministicMasternodes();
void RemoveNonDeterministicMasternodes();
/// 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 uint256& proTxHash, masternode_info_t& mnInfoRet);
bool GetMasternodeInfo(const COutPoint& outpoint, masternode_info_t& mnInfoRet);
bool GetMasternodeInfo(const CKeyID& keyIDOperator, 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();
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 GetMasternodeRank(const COutPoint &outpoint, int& nRankRet, uint256& blockHashRet, 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 CheckVerifyRequestAddr(const CAddress& addr, CConnman& connman);
void PrepareVerifyRequest(const CAddress& addr, 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& keyIDOperator, 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, bool forceAddedChecks = false, bool forceRemovedChecks = false);
void DoMaintenance(CConnman &connman);
};
#endif