// 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 MASTERNODE_PAYMENTS_H #define MASTERNODE_PAYMENTS_H #include "util.h" #include "core_io.h" #include "key.h" #include "masternode.h" #include "net_processing.h" #include "utilstrencodings.h" class CMasternodePayments; class CMasternodePaymentVote; class CMasternodeBlockPayees; static const int MNPAYMENTS_SIGNATURES_REQUIRED = 6; static const int MNPAYMENTS_SIGNATURES_TOTAL = 10; //! minimum peer version that can receive and send masternode payment messages, // vote for masternode and be elected as a payment winner // V1 - Last protocol version before update // V2 - Newest protocol version static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_1 = 70206; static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_2 = 70206; extern CCriticalSection cs_vecPayees; extern CCriticalSection cs_mapMasternodeBlocks; extern CCriticalSection cs_mapMasternodePayeeVotes; extern CMasternodePayments mnpayments; /// TODO: all 4 functions do not belong here really, they should be refactored/moved somewhere (main.cpp ?) bool IsBlockValueValid(const CBlock& block, int nBlockHeight, CAmount blockReward, std::string &strErrorRet); bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward); void FillBlockPayments(CMutableTransaction& txNew, int nBlockHeight, CAmount blockReward, CTxOut& txoutMasternodeRet, std::vector& voutSuperblockRet); std::string GetRequiredPaymentsString(int nBlockHeight); class CMasternodePayee { private: CScript scriptPubKey; std::vector vecVoteHashes; public: CMasternodePayee() : scriptPubKey(), vecVoteHashes() {} CMasternodePayee(CScript payee, uint256 hashIn) : scriptPubKey(payee), vecVoteHashes() { vecVoteHashes.push_back(hashIn); } ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(*(CScriptBase*)(&scriptPubKey)); READWRITE(vecVoteHashes); } CScript GetPayee() { return scriptPubKey; } void AddVoteHash(uint256 hashIn) { vecVoteHashes.push_back(hashIn); } std::vector GetVoteHashes() { return vecVoteHashes; } int GetVoteCount() { return vecVoteHashes.size(); } }; // Keep track of votes for payees from masternodes class CMasternodeBlockPayees { public: int nBlockHeight; std::vector vecPayees; CMasternodeBlockPayees() : nBlockHeight(0), vecPayees() {} CMasternodeBlockPayees(int nBlockHeightIn) : nBlockHeight(nBlockHeightIn), vecPayees() {} ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(nBlockHeight); READWRITE(vecPayees); } void AddPayee(const CMasternodePaymentVote& vote); bool GetBestPayee(CScript& payeeRet); bool HasPayeeWithVotes(const CScript& payeeIn, int nVotesReq); bool IsTransactionValid(const CTransaction& txNew); std::string GetRequiredPaymentsString(); }; // vote for the winning payment class CMasternodePaymentVote { public: CTxIn vinMasternode; int nBlockHeight; CScript payee; std::vector vchSig; CMasternodePaymentVote() : vinMasternode(), nBlockHeight(0), payee(), vchSig() {} CMasternodePaymentVote(CTxIn vinMasternode, int nBlockHeight, CScript payee) : vinMasternode(vinMasternode), nBlockHeight(nBlockHeight), payee(payee), vchSig() {} ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(vinMasternode); READWRITE(nBlockHeight); READWRITE(*(CScriptBase*)(&payee)); READWRITE(vchSig); } uint256 GetHash() const { CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); ss << *(CScriptBase*)(&payee); ss << nBlockHeight; ss << vinMasternode.prevout; return ss.GetHash(); } bool Sign(); bool CheckSignature(const CPubKey& pubKeyMasternode, int nValidationHeight, int &nDos); bool IsValid(CNode* pnode, int nValidationHeight, std::string& strError); void Relay(); bool IsVerified() { return !vchSig.empty(); } void MarkAsNotVerified() { vchSig.clear(); } std::string ToString() const; }; // // Masternode Payments Class // Keeps track of who should get paid for which blocks // class CMasternodePayments { private: // masternode count times nStorageCoeff payments blocks should be stored ... const float nStorageCoeff; // ... but at least nMinBlocksToStore (payments blocks) const int nMinBlocksToStore; // Keep track of current block index const CBlockIndex *pCurrentBlockIndex; public: std::map mapMasternodePaymentVotes; std::map mapMasternodeBlocks; std::map mapMasternodesLastVote; CMasternodePayments() : nStorageCoeff(1.25), nMinBlocksToStore(5000) {} ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(mapMasternodePaymentVotes); READWRITE(mapMasternodeBlocks); } void Clear(); bool AddPaymentVote(const CMasternodePaymentVote& vote); bool HasVerifiedPaymentVote(uint256 hashIn); bool ProcessBlock(int nBlockHeight); void Sync(CNode* node); void RequestLowDataPaymentBlocks(CNode* pnode); void CheckAndRemove(); bool GetBlockPayee(int nBlockHeight, CScript& payee); bool IsTransactionValid(const CTransaction& txNew, int nBlockHeight); bool IsScheduled(CMasternode& mn, int nNotBlockHeight); bool CanVote(COutPoint outMasternode, int nBlockHeight); int GetMinMasternodePaymentsProto(); void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv); std::string GetRequiredPaymentsString(int nBlockHeight); void FillBlockPayee(CMutableTransaction& txNew, int nBlockHeight, CAmount blockReward, CTxOut& txoutMasternodeRet); std::string ToString() const; int GetBlockCount() { return mapMasternodeBlocks.size(); } int GetVoteCount() { return mapMasternodePaymentVotes.size(); } bool IsEnoughData(); int GetStorageLimit(); void UpdatedBlockTip(const CBlockIndex *pindex); }; #endif