// 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 "timedata.h" #define MASTERNODE_MIN_CONFIRMATIONS 15 #define MASTERNODE_MIN_MNP_SECONDS (10*60) #define MASTERNODE_MIN_MNB_SECONDS (5*60) #define MASTERNODE_PING_SECONDS (5*60) #define MASTERNODE_EXPIRATION_SECONDS (65*60) #define MASTERNODE_REMOVAL_SECONDS (75*60) #define MASTERNODE_CHECK_SECONDS 5 using namespace std; class CMasternode; class CMasternodeBroadcast; class CMasternodePing; extern map mapCacheBlockHashes; bool GetBlockHash(uint256& hash, int nBlockHeight); // // The Masternode Ping Class : Contains a different serialize method for sending pings from masternodes throughout the network // class CMasternodePing { public: CTxIn vin; uint256 blockHash; int64_t sigTime; //mnb message times std::vector vchSig; //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(blockHash); READWRITE(sigTime); READWRITE(vchSig); } bool CheckAndUpdate(int& nDos, bool fRequireEnabled = true); bool Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode); void Relay(); uint256 GetHash(){ CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); ss << vin; ss << sigTime; return ss.GetHash(); } void swap(CMasternodePing& first, CMasternodePing& 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.blockHash, second.blockHash); swap(first.sigTime, second.sigTime); swap(first.vchSig, second.vchSig); } CMasternodePing& operator=(CMasternodePing from) { swap(*this, from); return *this; } friend bool operator==(const CMasternodePing& a, const CMasternodePing& b) { return a.vin == b.vin && a.blockHash == b.blockHash; } friend bool operator!=(const CMasternodePing& a, const CMasternodePing& b) { return !(a == b); } }; // // 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; int64_t lastTimeChecked; 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; //mnb message time int cacheInputAge; int cacheInputAgeBlock; bool unitTest; bool allowFreeTx; int protocolVersion; int64_t nLastDsq; //the dsq count from the last dsq broadcast of this node int nScanningErrorCount; int nLastScanningErrorBlockHeight; CMasternodePing lastPing; CMasternode(); CMasternode(const CMasternode& other); CMasternode(const CMasternodeBroadcast& mnb); 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.lastPing, second.lastPing); 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.nScanningErrorCount, second.nScanningErrorCount); swap(first.nLastScanningErrorBlockHeight, second.nLastScanningErrorBlockHeight); } 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(protocolVersion); READWRITE(activeState); READWRITE(lastPing); READWRITE(cacheInputAge); READWRITE(cacheInputAgeBlock); READWRITE(unitTest); READWRITE(allowFreeTx); READWRITE(nLastDsq); READWRITE(nScanningErrorCount); READWRITE(nLastScanningErrorBlockHeight); } int64_t SecondsSincePayment(); void UpdateFromNewBroadcast(CMasternodeBroadcast& mnb); inline uint64_t SliceHash(uint256& hash, int slice) { uint64_t n = 0; memcpy(&n, &hash+slice*64, 64); return n; } void Check(bool forceCheck = false); bool IsBroadcastedWithin(int seconds) { return (GetAdjustedTime() - sigTime) < seconds; } bool IsPingedWithin(int seconds, int64_t now = -1) { now == -1 ? now = GetAdjustedTime() : now; return (lastPing == CMasternodePing()) ? false : now - lastPing.sigTime < seconds; } void Disable() { sigTime = 0; lastPing = CMasternodePing(); } 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); } 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; } int64_t GetLastPaid(); }; // // 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); CMasternodeBroadcast(const CMasternode& mn); bool CheckAndUpdate(int& nDoS); bool CheckInputsAndAdd(int& nDos); bool Sign(CKey& keyCollateralAddress); void Relay(); 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(protocolVersion); READWRITE(lastPing); READWRITE(nLastDsq); } uint256 GetHash(){ CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); ss << sigTime; ss << pubkey; return ss.GetHash(); } }; #endif