// Copyright (c) 2014-2015 The Dash developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef MASTERNODE_H #define MASTERNODE_H #include "sync.h" #include "net.h" #include "key.h" #include "util.h" #include "base58.h" #include "main.h" #include "masternode.h" #include "masternode-pos.h" #include "timedata.h" #define MASTERNODE_NOT_PROCESSED 0 // initial state #define MASTERNODE_IS_CAPABLE 1 #define MASTERNODE_NOT_CAPABLE 2 #define MASTERNODE_STOPPED 3 #define MASTERNODE_INPUT_TOO_NEW 4 #define MASTERNODE_PORT_NOT_OPEN 6 #define MASTERNODE_PORT_OPEN 7 #define MASTERNODE_SYNC_IN_PROCESS 8 #define MASTERNODE_REMOTELY_ENABLED 9 #define MASTERNODE_MIN_CONFIRMATIONS 15 #define MASTERNODE_MIN_MNP_SECONDS (30*60) #define MASTERNODE_MIN_DSEE_SECONDS (5*60) #define MASTERNODE_PING_SECONDS (15*60) #define MASTERNODE_EXPIRATION_SECONDS (65*60) #define MASTERNODE_REMOVAL_SECONDS (24*60*60) using namespace std; class CMasternode; class CMasternodeBroadcast; class CMasternodePing; extern map mapCacheBlockHashes; bool GetBlockHash(uint256& hash, int nBlockHeight); // // The Masternode Class. For managing the Darksend process. It contains the input of the 1000DRK, signature to prove // it's the one who own that ip address and code for calculating the payment election. // class CMasternode { private: // critical section to protect the inner data structures mutable CCriticalSection cs; public: enum state { MASTERNODE_ENABLED = 1, MASTERNODE_EXPIRED = 2, MASTERNODE_VIN_SPENT = 3, MASTERNODE_REMOVE = 4, MASTERNODE_POS_ERROR = 5 }; CTxIn vin; CService addr; CPubKey pubkey; CPubKey pubkey2; std::vector sig; int activeState; int64_t sigTime; //dsee message times int64_t lastMnping; int64_t lastTimeSeen; int cacheInputAge; int cacheInputAgeBlock; bool unitTest; bool allowFreeTx; int protocolVersion; int64_t nLastDsq; //the dsq count from the last dsq broadcast of this node CScript donationAddress; int donationPercentage; int nScanningErrorCount; int nLastScanningErrorBlockHeight; int64_t nLastPaid; int nVotedTimes; CMasternode(); CMasternode(const CMasternode& other); CMasternode(const CMasternodeBroadcast& other); CMasternode(CService newAddr, CTxIn newVin, CPubKey newPubkey, std::vector newSig, int64_t newSigTime, CPubKey newPubkey2, int protocolVersionIn, CScript newDonationAddress, int newDonationPercentage); void swap(CMasternode& first, CMasternode& second) // nothrow { // enable ADL (not necessary in our case, but good practice) using std::swap; // by swapping the members of two classes, // the two classes are effectively swapped swap(first.vin, second.vin); swap(first.addr, second.addr); swap(first.pubkey, second.pubkey); swap(first.pubkey2, second.pubkey2); swap(first.sig, second.sig); swap(first.activeState, second.activeState); swap(first.sigTime, second.sigTime); swap(first.lastMnping, second.lastMnping); swap(first.lastTimeSeen, second.lastTimeSeen); swap(first.cacheInputAge, second.cacheInputAge); swap(first.cacheInputAgeBlock, second.cacheInputAgeBlock); swap(first.unitTest, second.unitTest); swap(first.allowFreeTx, second.allowFreeTx); swap(first.protocolVersion, second.protocolVersion); swap(first.nLastDsq, second.nLastDsq); swap(first.donationAddress, second.donationAddress); swap(first.donationPercentage, second.donationPercentage); swap(first.nScanningErrorCount, second.nScanningErrorCount); swap(first.nLastScanningErrorBlockHeight, second.nLastScanningErrorBlockHeight); swap(first.nLastPaid, second.nLastPaid); swap(first.nVotedTimes, second.nVotedTimes); } CMasternode& operator=(CMasternode from) { swap(*this, from); return *this; } friend bool operator==(const CMasternode& a, const CMasternode& b) { return a.vin == b.vin; } friend bool operator!=(const CMasternode& a, const CMasternode& b) { return !(a.vin == b.vin); } uint256 CalculateScore(int mod=1, int64_t nBlockHeight=0); ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { LOCK(cs); READWRITE(vin); READWRITE(addr); READWRITE(pubkey); READWRITE(pubkey2); READWRITE(sig); READWRITE(sigTime); READWRITE(lastTimeSeen); READWRITE(protocolVersion); READWRITE(donationAddress); READWRITE(donationPercentage); READWRITE(nLastPaid); READWRITE(activeState); READWRITE(lastMnping); READWRITE(cacheInputAge); READWRITE(cacheInputAgeBlock); READWRITE(unitTest); READWRITE(allowFreeTx); READWRITE(nLastDsq); READWRITE(nScanningErrorCount); READWRITE(nLastScanningErrorBlockHeight); READWRITE(nVotedTimes); } int64_t SecondsSincePayment() { int64_t sec = (GetAdjustedTime() - nLastPaid); if(sec < 60*60*24*30) return sec; //if it's less than 30 days, give seconds CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); ss << vin; ss << sigTime; uint256 hash = ss.GetHash(); memcpy(&sec, &hash, 64); return sec; } void UpdateFromNewBroadcast(CMasternodeBroadcast& mnb); void UpdateLastSeen(int64_t override=0) { if(override == 0){ lastTimeSeen = GetAdjustedTime(); } else { lastTimeSeen = override; } } inline uint64_t SliceHash(uint256& hash, int slice) { uint64_t n = 0; memcpy(&n, &hash+slice*64, 64); return n; } void Check(); bool UpdatedWithin(int seconds) { // LogPrintf("UpdatedWithin %d, %d -- %d \n", GetAdjustedTime() , lastTimeSeen, (GetAdjustedTime() - lastTimeSeen) < seconds); return (GetAdjustedTime() - lastTimeSeen) < seconds; } void Disable() { lastTimeSeen = 0; } bool IsEnabled() { return activeState == MASTERNODE_ENABLED; } int GetMasternodeInputAge() { if(chainActive.Tip() == NULL) return 0; if(cacheInputAge == 0){ cacheInputAge = GetInputAge(vin); cacheInputAgeBlock = chainActive.Tip()->nHeight; } return cacheInputAge+(chainActive.Tip()->nHeight-cacheInputAgeBlock); } void ApplyScanningError(CMasternodeScanningError& mnse) { if(!mnse.IsValid()) return; if(mnse.nBlockHeight == nLastScanningErrorBlockHeight) return; nLastScanningErrorBlockHeight = mnse.nBlockHeight; if(mnse.nErrorType == SCANNING_SUCCESS){ nScanningErrorCount--; if(nScanningErrorCount < 0) nScanningErrorCount = 0; } else { //all other codes are equally as bad nScanningErrorCount++; if(nScanningErrorCount > MASTERNODE_SCANNING_ERROR_THESHOLD*2) nScanningErrorCount = MASTERNODE_SCANNING_ERROR_THESHOLD*2; } } std::string Status() { std::string strStatus = "ACTIVE"; if(activeState == CMasternode::MASTERNODE_ENABLED) strStatus = "ENABLED"; if(activeState == CMasternode::MASTERNODE_EXPIRED) strStatus = "EXPIRED"; if(activeState == CMasternode::MASTERNODE_VIN_SPENT) strStatus = "VIN_SPENT"; if(activeState == CMasternode::MASTERNODE_REMOVE) strStatus = "REMOVE"; if(activeState == CMasternode::MASTERNODE_POS_ERROR) strStatus = "POS_ERROR"; return strStatus; } }; // // The Masternode Broadcast Class : Contains a different serialize method for sending masternodes through the network // class CMasternodeBroadcast : public CMasternode { public: CMasternodeBroadcast(); CMasternodeBroadcast(CService newAddr, CTxIn newVin, CPubKey newPubkey, CPubKey newPubkey2, int protocolVersionIn, CScript newDonationAddress, int newDonationPercentage); CMasternodeBroadcast(const CMasternode& other); bool CheckAndUpdate(int& nDoS, bool fRequested); bool CheckInputsAndAdd(int& nDos, bool fRequested); bool Sign(CKey& keyCollateralAddress); void Relay(bool fRequested); ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(vin); READWRITE(addr); READWRITE(pubkey); READWRITE(pubkey2); READWRITE(sig); READWRITE(sigTime); READWRITE(lastTimeSeen); READWRITE(protocolVersion); READWRITE(donationAddress); READWRITE(donationPercentage); READWRITE(nLastPaid); } uint256 GetHash(){ return Hash( BEGIN(sigTime), END(sigTime), BEGIN(pubkey), END(pubkey) ); } }; // // The Masternode Ping Class : Contains a different serialize method for sending pings from masternodes throughout the network // class CMasternodePing { public: CTxIn vin; std::vector vchSig; int64_t sigTime; //dsee message times //removed stop CMasternodePing(); CMasternodePing(CTxIn& newVin); ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(vin); READWRITE(sigTime); READWRITE(vchSig); } bool CheckAndUpdate(int& nDos); bool Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode); void Relay(); uint256 GetHash(){ return Hash(BEGIN(vin), END(vin), BEGIN(sigTime), END(sigTime)); } }; #endif