// Copyright (c) 2014-2016 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 "main.h" #include "masternode.h" #include "utilstrencodings.h" #include using namespace std; //! minimum peer version that can receive and send masternode payment messages, // vote for masternode winner and be elected as a winner // V1 - Last protocol version before update // V2 - Newest protocol version static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_1 = 70103; static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_2 = 70201; extern CCriticalSection cs_vecPayees; extern CCriticalSection cs_mapMasternodeBlocks; extern CCriticalSection cs_mapMasternodePayeeVotes; class CMasternodePayments; class CMasternodePaymentWinner; class CMasternodeBlockPayees; extern CMasternodePayments mnpayments; #define MNPAYMENTS_SIGNATURES_REQUIRED 6 #define MNPAYMENTS_SIGNATURES_TOTAL 10 void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv); bool IsReferenceNode(CTxIn& vin); /// 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); 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 { public: CScript scriptPubKey; int nVotes; CMasternodePayee() { scriptPubKey = CScript(); nVotes = 0; } CMasternodePayee(CScript payee, int nVotesIn) { scriptPubKey = payee; nVotes = nVotesIn; } ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(*(CScriptBase*)(&scriptPubKey)); READWRITE(nVotes); } }; // Keep track of votes for payees from masternodes class CMasternodeBlockPayees { public: int nBlockHeight; std::vector vecPayees; CMasternodeBlockPayees() : nBlockHeight(0) {} CMasternodeBlockPayees(int nBlockHeightIn) : nBlockHeight(nBlockHeightIn) {} ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(nBlockHeight); READWRITE(vecPayees); } void AddPayee(CMasternodePaymentWinner winner); bool GetPayee(CScript& payeeRet); bool HasPayeeWithVotes(CScript payeeIn, int nVotesReq); bool IsTransactionValid(const CTransaction& txNew); std::string GetRequiredPaymentsString(); }; // for storing the winning payments class CMasternodePaymentWinner { public: CTxIn vinMasternode; int nBlockHeight; CScript payee; std::vector vchSig; CMasternodePaymentWinner() { nBlockHeight = 0; vinMasternode = CTxIn(); payee = CScript(); } CMasternodePaymentWinner(CTxIn vinIn) { nBlockHeight = 0; vinMasternode = vinIn; payee = CScript(); } uint256 GetHash(){ CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); ss << *(CScriptBase*)(&payee); ss << nBlockHeight; ss << vinMasternode.prevout; return ss.GetHash(); } bool Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode); bool IsValid(CNode* pnode, int nValidationHeight, std::string& strError); bool SignatureValid(); void Relay(); void AddPayee(CScript payeeIn){ payee = payeeIn; } 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); } std::string ToString() { std::string ret = ""; ret += vinMasternode.ToString(); ret += ", " + boost::lexical_cast(nBlockHeight); ret += ", " + ScriptToAsmStr(payee); ret += ", " + boost::lexical_cast((int)vchSig.size()); return ret; } }; // // Masternode Payments Class // Keeps track of who should get paid for which blocks // class CMasternodePayments { private: const int nMinBlocksToStore; const float nStorageCoeff; // Keep track of current block index const CBlockIndex *pCurrentBlockIndex; public: std::map mapMasternodePayeeVotes; std::map mapMasternodeBlocks; std::map mapMasternodesLastVote; CMasternodePayments() : nMinBlocksToStore(4000), nStorageCoeff(1.25) { } void Clear() { LOCK2(cs_mapMasternodeBlocks, cs_mapMasternodePayeeVotes); mapMasternodeBlocks.clear(); mapMasternodePayeeVotes.clear(); } bool AddWinningMasternode(CMasternodePaymentWinner& winner); bool ProcessBlock(int nBlockHeight); void Sync(CNode* node, int nCountNeeded); void CheckAndRemove(); int LastPayment(CMasternode& mn); 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 GetOldestBlock(); int GetNewestBlock(); int GetBlockCount() { return mapMasternodeBlocks.size(); } int GetVoteCount() { return mapMasternodePayeeVotes.size(); } bool IsEnoughData(int nMnCount); int GetStorageLimit(); ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(mapMasternodePayeeVotes); READWRITE(mapMasternodeBlocks); } void UpdatedBlockTip(const CBlockIndex *pindex); }; #endif