text: 
  // Copyright (c) 2014-2015 The Dash developers
  // Copyright (c) 2015-2017 The PIVX developers 
  // Copyright (c) 2015-2017 The ALQO 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 "base58.h"
  #include "key.h"
  #include "main.h"
  #include "net.h"
  #include "sync.h"
  #include "timedata.h"
  #include "util.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 (120 * 60)
  #define MASTERNODE_REMOVAL_SECONDS (130 * 60)
  #define MASTERNODE_CHECK_SECONDS 5
  
  using namespace std;
  
  class CMasternode;
  class CMasternodeBroadcast;
  class CMasternodePing;
  extern map<int64_t, uint256> 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<unsigned char> vchSig;
      //removed stop
  
      CMasternodePing();
      CMasternodePing(CTxIn& newVin);
  
      ADD_SERIALIZE_METHODS;
  
      template <typename Stream, typename Operation>
      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 1000 CBRX, 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_PRE_ENABLED,
          MASTERNODE_ENABLED,
          MASTERNODE_EXPIRED,
          MASTERNODE_OUTPOINT_SPENT,
          MASTERNODE_REMOVE,
          MASTERNODE_WATCHDOG_EXPIRED,
          MASTERNODE_POSE_BAN,
          MASTERNODE_VIN_SPENT,
          MASTERNODE_POS_ERROR
      };
  
      CTxIn vin;
      CService addr;
      CPubKey pubKeyCollateralAddress;
      CPubKey pubKeyMasternode;
      CPubKey pubKeyCollateralAddress1;
      CPubKey pubKeyMasternode1;
      std::vector<unsigned char> sig;
      int activeState;
      int64_t sigTime; //mnb message time
      int cacheInputAge;
      int cacheInputAgeBlock;
      bool unitTest;
      bool allowFreeTx;
      int protocolVersion;
      int nActiveState;
      int64_t nLastDsq; //the dsq count from the last dsq broadcast of this node
      int nScanningErrorCount;
      int nLastScanningErrorBlockHeight;
      CMasternodePing lastPing;
  
      int64_t nLastDsee;  // temporary, do not save. Remove after migration to v12
      int64_t nLastDseep; // temporary, do not save. Remove after migration to v12
  
      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.pubKeyCollateralAddress, second.pubKeyCollateralAddress);
          swap(first.pubKeyMasternode, second.pubKeyMasternode);
          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 <typename Stream, typename Operation>
      inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion)
      {
          LOCK(cs);
  
          READWRITE(vin);
          READWRITE(addr);
          READWRITE(pubKeyCollateralAddress);
          READWRITE(pubKeyMasternode);
          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();
  
      bool 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 GetStatus();
  
      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();
      bool IsValidNetAddr();
  };
  
  
  //
  // 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 <typename Stream, typename Operation>
      inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion)
      {
          READWRITE(vin);
          READWRITE(addr);
          READWRITE(pubKeyCollateralAddress);
          READWRITE(pubKeyMasternode);
          READWRITE(sig);
          READWRITE(sigTime);
          READWRITE(protocolVersion);
          READWRITE(lastPing);
          READWRITE(nLastDsq);
      }
  
      uint256 GetHash()
      {
          CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
          ss << sigTime;
          ss << pubKeyCollateralAddress;
          return ss.GetHash();
      }
  
      /// Create Masternode broadcast, needs to be relayed manually after that
      static bool Create(CTxIn vin, CService service, CKey keyCollateralAddressNew, CPubKey pubKeyCollateralAddressNew, CKey keyMasternodeNew, CPubKey pubKeyMasternodeNew, std::string& strErrorRet, CMasternodeBroadcast& mnbRet);
      static bool Create(std::string strService, std::string strKey, std::string strTxHash, std::string strOutputIndex, std::string& strErrorRet, CMasternodeBroadcast& mnbRet, bool fOffline = false);
  };
  
  #endif
  