// 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 = 70210; static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_2 = 70210; extern CCriticalSection cs_vecPayees; extern CCriticalSection cs_mapMasternodeBlocks; 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, std::vector& voutMasternodePaymentsRet, std::vector& voutSuperblockPaymentsRet); std::map GetRequiredPaymentsStrings(int nStartHeight, int nEndHeight); 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) { READWRITE(*(CScriptBase*)(&scriptPubKey)); READWRITE(vecVoteHashes); } CScript GetPayee() const { return scriptPubKey; } void AddVoteHash(uint256 hashIn) { vecVoteHashes.push_back(hashIn); } std::vector GetVoteHashes() const { return vecVoteHashes; } int GetVoteCount() const { 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) { READWRITE(nBlockHeight); READWRITE(vecPayees); } void AddPayee(const CMasternodePaymentVote& vote); bool GetBestPayee(CScript& payeeRet) const; bool HasPayeeWithVotes(const CScript& payeeIn, int nVotesReq) const; bool IsTransactionValid(const CTransaction& txNew) const; std::string GetRequiredPaymentsString() const; }; // vote for the winning payment class CMasternodePaymentVote { public: COutPoint masternodeOutpoint; int nBlockHeight; CScript payee; std::vector vchSig; CMasternodePaymentVote() : masternodeOutpoint(), nBlockHeight(0), payee(), vchSig() {} CMasternodePaymentVote(COutPoint outpoint, int nBlockHeight, CScript payee) : masternodeOutpoint(outpoint), nBlockHeight(nBlockHeight), payee(payee), vchSig() {} ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(masternodeOutpoint); READWRITE(nBlockHeight); READWRITE(*(CScriptBase*)(&payee)); if (!(s.GetType() & SER_GETHASH)) { READWRITE(vchSig); } } uint256 GetHash() const; uint256 GetSignatureHash() const; bool Sign(); bool CheckSignature(const CKeyID& keyIDOperator, int nValidationHeight, int &nDos) const; bool IsValid(CNode* pnode, int nValidationHeight, std::string& strError, CConnman& connman) const; void Relay(CConnman& connman) const; bool IsVerified() const { 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 height int nCachedBlockHeight; public: std::map mapMasternodePaymentVotes; std::map mapMasternodeBlocks; std::map mapMasternodesLastVote; std::map mapMasternodesDidNotVote; CMasternodePayments() : nStorageCoeff(1.25), nMinBlocksToStore(6000) {} ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(mapMasternodePaymentVotes); READWRITE(mapMasternodeBlocks); } void Clear(); bool AddOrUpdatePaymentVote(const CMasternodePaymentVote& vote); bool HasVerifiedPaymentVote(const uint256& hashIn) const; bool ProcessBlock(int nBlockHeight, CConnman& connman); void CheckBlockVotes(int nBlockHeight); void Sync(CNode* node, CConnman& connman) const; void RequestLowDataPaymentBlocks(CNode* pnode, CConnman& connman) const; void CheckAndRemove(); bool GetBlockTxOuts(int nBlockHeight, CAmount blockReward, std::vector& voutMasternodePaymentsRet) const; bool IsTransactionValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward) const; bool IsScheduled(const masternode_info_t& mnInfo, int nNotBlockHeight) const; bool UpdateLastVote(const CMasternodePaymentVote& vote); int GetMinMasternodePaymentsProto() const; void ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman); std::string GetRequiredPaymentsString(int nBlockHeight) const; bool GetMasternodeTxOuts(int nBlockHeight, CAmount blockReward, std::vector& voutMasternodePaymentsRet) const; std::string ToString() const; int GetBlockCount() const { return mapMasternodeBlocks.size(); } int GetVoteCount() const { return mapMasternodePaymentVotes.size(); } bool IsEnoughData() const; int GetStorageLimit() const; void UpdatedBlockTip(const CBlockIndex *pindex, CConnman& connman); void DoMaintenance(); }; #endif