// 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 GOVERANCE_H #define GOVERANCE_H #include "main.h" #include "sync.h" #include "net.h" #include "key.h" #include "util.h" #include "base58.h" #include "masternode.h" #include "governance-vote.h" #include #include "init.h" using namespace std; extern CCriticalSection cs_budget; class CGovernanceManager; class CBudgetProposal; class CBudgetVote; // todo - 12.1 - change BUDGET_ to GOVERNANCE_ (cherry pick) static const CAmount GOVERNANCE_FEE_TX = (5*COIN); static const int64_t GOVERNANCE_FEE_CONFIRMATIONS = 6; static const int64_t GOVERNANCE_UPDATE_MIN = 60*60; extern std::vector vecImmatureBudgetProposals; extern std::map askedForSourceProposalOrBudget; extern CGovernanceManager governance; //Check the collateral transaction for the budget proposal/finalized budget extern bool IsCollateralValid(uint256 nTxCollateralHash, uint256 nExpectedHash, std::string& strError, int64_t& nTime, int& nConf, CAmount minFee); // // Governance Manager : Contains all proposals for the budget // class CGovernanceManager { private: //hold txes until they mature enough to use map mapCollateral; // Keep track of current block index const CBlockIndex *pCurrentBlockIndex; public: // critical section to protect the inner data structures mutable CCriticalSection cs; // keep track of the scanning errors I've seen map mapProposals; // todo - 12.1 - move to private for better encapsulation std::map mapSeenMasternodeBudgetProposals; std::map mapSeenMasternodeBudgetVotes; std::map mapOrphanMasternodeBudgetVotes; // parent hash vote hash vote std::map > mapVotes; CGovernanceManager() { mapProposals.clear(); } void ClearSeen() { mapSeenMasternodeBudgetProposals.clear(); mapSeenMasternodeBudgetVotes.clear(); } int CountProposalInventoryItems() { return mapSeenMasternodeBudgetProposals.size() + mapSeenMasternodeBudgetVotes.size(); } int sizeProposals() {return (int)mapProposals.size();} // description: incremental sync with our peers // note: incremental syncing seems excessive, well just have clients ask for specific objects and their votes // note: 12.1 - remove //void ResetSync(); //void MarkSynced(); void Sync(CNode* node, uint256 nProp); void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv); void NewBlock(); CBudgetProposal *FindProposal(const std::string &strProposalName); CBudgetProposal *FindProposal(uint256 nHash); std::vector GetBudget(); std::vector GetAllProposals(); bool IsBudgetPaymentBlock(int nBlockHeight); bool AddProposal(CBudgetProposal& budgetProposal); bool UpdateProposal(CBudgetVote& vote, CNode* pfrom, std::string& strError); bool AddOrUpdateVote(CBudgetVote& vote, std::string& strError); bool PropExists(uint256 nHash); std::string GetRequiredPaymentsString(int nBlockHeight); void CheckOrphanVotes(); void Clear(){ LOCK(cs); LogPrintf("Budget object cleared\n"); mapProposals.clear(); mapSeenMasternodeBudgetProposals.clear(); mapSeenMasternodeBudgetVotes.clear(); mapOrphanMasternodeBudgetVotes.clear(); } void CheckAndRemove(); std::string ToString() const; ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(mapSeenMasternodeBudgetProposals); READWRITE(mapSeenMasternodeBudgetVotes); READWRITE(mapOrphanMasternodeBudgetVotes); READWRITE(mapProposals); READWRITE(mapVotes); } void UpdatedBlockTip(const CBlockIndex *pindex); }; /** * Governance objects can hold any time of data * -------------------------------------------- * * */ // todo - 12.1 - add payload obj to CGovernanceObj // union GovernanceObjectPayload // { // CAmount nAmount; // int nValue; // bool bIsActive; // std::string strPayload; // double fValue; // } /** * Governance object payload types * -------------------------------------------- * * */ // todo - 12.1 - add payload obj to CGovernanceObj // enum class GovernanceObjectPayloadType { // CAmount, // Int, // Bool, // String, // Double // }; // // Budget Proposal : Contains the masternode votes for each budget // class CBudgetProposal { private: // critical section to protect the inner data structures mutable CCriticalSection cs; CAmount nAlloted; public: bool fValid; std::string strProposalName; /* json object with name, short-description, long-description, pdf-url and any other info This allows the proposal website to stay 100% decentralized */ std::string strURL; int nBlockStart; //int nStartTime; int nBlockEnd; //int nExpirationTime; CAmount nValue; // 12.1 - remove // int nPriority; //budget is sorted by this integer before funding votecount // GovernanceObjectPayloadType payloadType; // GovernanceObjectPayload payload; CScript address; //todo rename to addressOwner; int64_t nTime; uint256 nFeeTXHash; uint256 nHashParent; // 12.1 - remove //cache object CBudgetProposal(); CBudgetProposal(const CBudgetProposal& other); CBudgetProposal(std::string strProposalNameIn, std::string strURLIn, int nPaymentCount, CScript addressIn, CAmount nAmountIn, int nBlockStartIn, uint256 nFeeTXHashIn); bool HasMinimumRequiredSupport(); bool IsValid(const CBlockIndex* pindex, std::string& strError, bool fCheckCollateral=true); bool IsEstablished(); std::string GetName() {return strProposalName; } std::string GetURL() {return strURL; } int GetBlockStart() {return nBlockStart;} int GetBlockEnd() {return nBlockEnd;} CScript GetPayee() {return address;} int GetTotalPaymentCount(); int GetRemainingPaymentCount(int nBlockHeight); int GetBlockStartCycle(); int GetBlockCurrentCycle(const CBlockIndex* pindex); int GetBlockEndCycle(); double GetRatio(); int GetAbsoluteYesCount(); int GetYesCount(); int GetNoCount(); int GetAbstainCount(); CAmount GetAmount() {return nAmount;} void SetAllotted(CAmount nAllotedIn) {nAlloted = nAllotedIn;} CAmount GetAllotted() {return nAlloted;} void CleanAndRemove(bool fSignatureCheck); uint256 GetHash(){ CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); ss << strProposalName; ss << strURL; ss << nBlockStart; ss << nBlockEnd; ss << nAmount; ss << *(CScriptBase*)(&address); uint256 h1 = ss.GetHash(); return h1; } ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { //for syncing with other clients READWRITE(LIMITED_STRING(strProposalName, 20)); READWRITE(LIMITED_STRING(strURL, 64)); READWRITE(nTime); READWRITE(nBlockStart); READWRITE(nBlockEnd); READWRITE(nAmount); READWRITE(*(CScriptBase*)(&address)); READWRITE(nTime); READWRITE(nFeeTXHash); } }; // // CBudgetVote - Allow a masternode node to vote and broadcast throughout the network // class CBudgetVote { public: bool fValid; //if the vote is currently valid / counted bool fSynced; //if we've sent this to our peers CTxIn vin; uint256 nProposalHash; int nVote; //int nVoteType; //12.1 - mapped to config values int64_t nTime; std::vector vchSig; CBudgetVote(); CBudgetVote(CTxIn vin, uint256 nProposalHash, int nVoteIn); bool Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode); bool IsValid(bool fSignatureCheck); void Relay(); std::string GetVoteString() { std::string ret = "ABSTAIN"; if(nVote == VOTE_YES) ret = "YES"; if(nVote == VOTE_NO) ret = "NO"; return ret; } uint256 GetHash(){ CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); ss << vin; ss << nProposalHash; ss << nVote; ss << nTime; return ss.GetHash(); } ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(vin); READWRITE(nProposalHash); READWRITE(nVote); READWRITE(nTime); READWRITE(vchSig); } }; #endif