2016-04-09 21:57:53 +02:00
|
|
|
// 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.
|
2016-04-09 22:31:01 +02:00
|
|
|
#ifndef GOVERANCE_H
|
|
|
|
#define GOVERANCE_H
|
2016-04-09 21:57:53 +02:00
|
|
|
|
|
|
|
#include "main.h"
|
|
|
|
#include "sync.h"
|
|
|
|
#include "net.h"
|
|
|
|
#include "key.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "base58.h"
|
|
|
|
#include "masternode.h"
|
2016-04-14 00:41:40 +02:00
|
|
|
#include "governance-vote.h"
|
2016-04-09 21:57:53 +02:00
|
|
|
#include <boost/lexical_cast.hpp>
|
|
|
|
#include "init.h"
|
|
|
|
|
2016-04-16 19:19:17 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2016-04-09 21:57:53 +02:00
|
|
|
using namespace std;
|
|
|
|
extern CCriticalSection cs_budget;
|
|
|
|
|
2016-04-15 04:54:11 +02:00
|
|
|
// note: is there a reason these are static?
|
|
|
|
// http://stackoverflow.com/questions/3709207/c-semantics-of-static-const-vs-const
|
|
|
|
static const CAmount BUDGET_FEE_TX = (5*COIN);
|
|
|
|
static const int64_t BUDGET_FEE_CONFIRMATIONS = 6;
|
|
|
|
static const int64_t BUDGET_VOTE_UPDATE_MIN = 60*60;
|
|
|
|
static const int64_t CONTRACT_ACTIVATION_TIME = 60*60*24*14;
|
|
|
|
|
|
|
|
|
2016-04-09 22:31:01 +02:00
|
|
|
class CGovernanceManager;
|
2016-04-16 19:19:17 +02:00
|
|
|
class CGovernanceObject;
|
2016-05-23 19:53:05 +02:00
|
|
|
class CGovernanceVote;
|
2016-04-14 20:53:46 +02:00
|
|
|
class CNode;
|
2016-04-09 21:57:53 +02:00
|
|
|
|
|
|
|
// todo - 12.1 - change BUDGET_ to GOVERNANCE_ (cherry pick)
|
2016-04-10 02:43:15 +02:00
|
|
|
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;
|
2016-04-09 21:57:53 +02:00
|
|
|
|
2016-04-16 19:19:17 +02:00
|
|
|
extern std::vector<CGovernanceObject> vecImmatureBudgetProposals;
|
2016-04-12 18:00:19 +02:00
|
|
|
extern std::map<uint256, int64_t> askedForSourceProposalOrBudget;
|
2016-04-10 16:46:19 +02:00
|
|
|
extern CGovernanceManager governance;
|
2016-04-09 21:57:53 +02:00
|
|
|
|
2016-05-13 18:03:01 +02:00
|
|
|
// FOR SEEN MAP ARRAYS - GOVERNANCE OBJECTS AND VOTES
|
|
|
|
#define SEEN_OBJECT_IS_VALID 0
|
|
|
|
#define SEEN_OBJECT_ERROR_INVALID 1
|
|
|
|
#define SEEN_OBJECT_ERROR_IMMATURE 2
|
|
|
|
|
2016-04-09 21:57:53 +02:00
|
|
|
//Check the collateral transaction for the budget proposal/finalized budget
|
2016-04-12 18:00:19 +02:00
|
|
|
extern bool IsCollateralValid(uint256 nTxCollateralHash, uint256 nExpectedHash, std::string& strError, int64_t& nTime, int& nConf, CAmount minFee);
|
2016-04-09 21:57:53 +02:00
|
|
|
|
|
|
|
|
|
|
|
//
|
2016-04-09 22:31:01 +02:00
|
|
|
// Governance Manager : Contains all proposals for the budget
|
2016-04-09 21:57:53 +02:00
|
|
|
//
|
2016-04-09 22:31:01 +02:00
|
|
|
class CGovernanceManager
|
2016-04-09 21:57:53 +02:00
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
|
|
//hold txes until they mature enough to use
|
|
|
|
map<uint256, CTransaction> mapCollateral;
|
|
|
|
// Keep track of current block index
|
|
|
|
const CBlockIndex *pCurrentBlockIndex;
|
|
|
|
|
2016-04-19 18:51:15 +02:00
|
|
|
int64_t nTimeLastDiff;
|
|
|
|
|
2016-04-09 21:57:53 +02:00
|
|
|
public:
|
|
|
|
// critical section to protect the inner data structures
|
|
|
|
mutable CCriticalSection cs;
|
|
|
|
|
|
|
|
// keep track of the scanning errors I've seen
|
2016-05-13 18:03:01 +02:00
|
|
|
map<uint256, CGovernanceObject> mapObjects;
|
2016-04-09 21:57:53 +02:00
|
|
|
|
2016-04-14 00:41:40 +02:00
|
|
|
// todo - 12.1 - move to private for better encapsulation
|
2016-05-23 19:53:05 +02:00
|
|
|
std::map<uint256, int> mapSeenGovernanceObjects;
|
|
|
|
std::map<uint256, int> mapSeenVotes;
|
|
|
|
std::map<uint256, CGovernanceVote> mapOrphanMasternodeBudgetVotes;
|
|
|
|
std::map<uint256, CGovernanceVote> mapVotes;
|
2016-04-09 21:57:53 +02:00
|
|
|
|
2016-04-09 22:31:01 +02:00
|
|
|
CGovernanceManager() {
|
2016-05-13 18:03:01 +02:00
|
|
|
mapObjects.clear();
|
2016-04-09 21:57:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClearSeen() {
|
2016-05-23 19:53:05 +02:00
|
|
|
mapSeenGovernanceObjects.clear();
|
|
|
|
mapSeenVotes.clear();
|
2016-04-09 21:57:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int CountProposalInventoryItems()
|
|
|
|
{
|
2016-05-23 19:53:05 +02:00
|
|
|
return mapSeenGovernanceObjects.size() + mapSeenVotes.size();
|
2016-04-09 21:57:53 +02:00
|
|
|
}
|
|
|
|
|
2016-05-13 18:03:01 +02:00
|
|
|
int sizeProposals() {return (int)mapObjects.size();}
|
2016-04-09 21:57:53 +02:00
|
|
|
|
2016-04-14 00:41:40 +02:00
|
|
|
// 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);
|
2016-04-09 21:57:53 +02:00
|
|
|
|
|
|
|
void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
|
|
|
|
void NewBlock();
|
2016-04-09 22:31:01 +02:00
|
|
|
|
2016-04-16 19:19:17 +02:00
|
|
|
CGovernanceObject *FindProposal(const std::string &strName);
|
|
|
|
CGovernanceObject *FindProposal(uint256 nHash);
|
2016-04-09 21:57:53 +02:00
|
|
|
|
2016-04-26 06:08:36 +02:00
|
|
|
std::vector<CGovernanceObject*> GetAllProposals(int64_t nMoreThanTime);
|
2016-04-09 22:31:01 +02:00
|
|
|
|
2016-05-23 19:53:05 +02:00
|
|
|
int CountMatchingVotes(int nVoteSignalIn, int nVoteOutcomeIn);
|
|
|
|
|
2016-04-09 21:57:53 +02:00
|
|
|
bool IsBudgetPaymentBlock(int nBlockHeight);
|
2016-04-16 19:19:17 +02:00
|
|
|
bool AddProposal(CGovernanceObject& budgetProposal);
|
2016-05-23 19:53:05 +02:00
|
|
|
bool UpdateProposal(CGovernanceVote& vote, CNode* pfrom, std::string& strError);
|
|
|
|
bool AddOrUpdateVote(CGovernanceVote& vote, std::string& strError);
|
2016-04-09 21:57:53 +02:00
|
|
|
bool PropExists(uint256 nHash);
|
|
|
|
std::string GetRequiredPaymentsString(int nBlockHeight);
|
2016-04-14 22:01:15 +02:00
|
|
|
void CleanAndRemove(bool fSignatureCheck);
|
2016-05-23 19:53:05 +02:00
|
|
|
void CheckAndRemove();
|
2016-04-09 21:57:53 +02:00
|
|
|
|
|
|
|
void CheckOrphanVotes();
|
|
|
|
void Clear(){
|
|
|
|
LOCK(cs);
|
|
|
|
|
|
|
|
LogPrintf("Budget object cleared\n");
|
2016-05-13 18:03:01 +02:00
|
|
|
mapObjects.clear();
|
2016-05-23 19:53:05 +02:00
|
|
|
mapSeenGovernanceObjects.clear();
|
|
|
|
mapSeenVotes.clear();
|
2016-04-09 21:57:53 +02:00
|
|
|
mapOrphanMasternodeBudgetVotes.clear();
|
|
|
|
}
|
|
|
|
std::string ToString() const;
|
|
|
|
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
|
|
|
|
template <typename Stream, typename Operation>
|
|
|
|
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
2016-05-23 19:53:05 +02:00
|
|
|
READWRITE(mapSeenGovernanceObjects);
|
|
|
|
READWRITE(mapSeenVotes);
|
2016-04-09 21:57:53 +02:00
|
|
|
READWRITE(mapOrphanMasternodeBudgetVotes);
|
2016-05-13 18:03:01 +02:00
|
|
|
READWRITE(mapObjects);
|
2016-04-14 03:52:26 +02:00
|
|
|
READWRITE(mapVotes);
|
2016-04-09 21:57:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void UpdatedBlockTip(const CBlockIndex *pindex);
|
2016-04-19 18:51:15 +02:00
|
|
|
int64_t GetLastDiffTime() {return nTimeLastDiff;}
|
|
|
|
void UpdateLastDiffTime(int64_t nTimeIn) {nTimeLastDiff=nTimeIn;}
|
2016-04-09 21:57:53 +02:00
|
|
|
};
|
|
|
|
|
2016-04-14 03:52:26 +02:00
|
|
|
/**
|
2016-04-16 19:19:17 +02:00
|
|
|
* Generic Governance Object
|
2016-04-14 03:52:26 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2016-04-16 19:19:17 +02:00
|
|
|
class CGovernanceObject
|
2016-04-09 21:57:53 +02:00
|
|
|
{
|
|
|
|
private:
|
|
|
|
// critical section to protect the inner data structures
|
|
|
|
mutable CCriticalSection cs;
|
|
|
|
CAmount nAlloted;
|
|
|
|
|
|
|
|
public:
|
2016-04-19 18:51:15 +02:00
|
|
|
|
|
|
|
uint256 nHashParent; //parent object, 0 is root
|
|
|
|
int nRevision; //object revision in the system
|
2016-04-16 19:19:17 +02:00
|
|
|
std::string strName; //org name, username, prop name, etc.
|
2016-04-26 06:08:36 +02:00
|
|
|
int64_t nTime; //time this object was created
|
|
|
|
uint256 nFeeTXHash; //fee-tx
|
2016-05-23 19:53:05 +02:00
|
|
|
std::string strData; // Data field - can be used for anything
|
|
|
|
|
2016-05-13 18:03:01 +02:00
|
|
|
// caching -- one per voting mechanism -- see governance-vote.h for more information
|
|
|
|
bool fCachedFunding;
|
|
|
|
bool fCachedValid;
|
|
|
|
bool fCachedDelete;
|
|
|
|
bool fCachedClearRegisters;
|
|
|
|
bool fCachedEndorsed;
|
|
|
|
bool fCachedReleaseBounty1;
|
|
|
|
bool fCachedReleaseBounty2;
|
|
|
|
bool fCachedReleaseBounty3;
|
2016-04-19 18:51:15 +02:00
|
|
|
|
2016-04-17 02:29:41 +02:00
|
|
|
CGovernanceObject();
|
2016-04-26 06:08:36 +02:00
|
|
|
CGovernanceObject(uint256 nHashParentIn, int nRevisionIn, std::string strNameIn, int64_t nTime, uint256 nFeeTXHashIn);
|
2016-04-26 13:42:34 +02:00
|
|
|
CGovernanceObject(const CGovernanceObject& other);
|
|
|
|
|
2016-04-26 06:08:36 +02:00
|
|
|
|
|
|
|
void swap(CGovernanceObject& first, CGovernanceObject& 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.strName, second.strName);
|
|
|
|
swap(first.nHashParent, second.nHashParent);
|
|
|
|
swap(first.nRevision, second.nRevision);
|
|
|
|
swap(first.nTime, second.nTime);
|
|
|
|
swap(first.nFeeTXHash, second.nFeeTXHash);
|
2016-05-23 19:53:05 +02:00
|
|
|
swap(first.strData, second.strData);
|
2016-05-13 18:03:01 +02:00
|
|
|
|
|
|
|
// swap all cached valid flags
|
|
|
|
swap(first.fCachedFunding, second.fCachedFunding);
|
|
|
|
swap(first.fCachedValid, second.fCachedValid);
|
|
|
|
swap(first.fCachedDelete, second.fCachedDelete);
|
|
|
|
swap(first.fCachedClearRegisters, second.fCachedClearRegisters);
|
|
|
|
swap(first.fCachedEndorsed, second.fCachedEndorsed);
|
|
|
|
swap(first.fCachedReleaseBounty1, second.fCachedReleaseBounty1);
|
|
|
|
swap(first.fCachedReleaseBounty2, second.fCachedReleaseBounty2);
|
|
|
|
swap(first.fCachedReleaseBounty3, second.fCachedReleaseBounty3);
|
|
|
|
|
2016-04-26 06:08:36 +02:00
|
|
|
}
|
2016-04-17 02:29:41 +02:00
|
|
|
|
|
|
|
bool HasMinimumRequiredSupport();
|
|
|
|
bool IsValid(const CBlockIndex* pindex, std::string& strError, bool fCheckCollateral=true);
|
|
|
|
|
|
|
|
std::string GetName() {return strName; }
|
2016-04-26 06:08:36 +02:00
|
|
|
|
|
|
|
// get vote counts on each outcome
|
2016-05-23 19:53:05 +02:00
|
|
|
int GetAbsoluteYesCount(int nVoteSignalIn);
|
|
|
|
int GetYesCount(int nVoteSignalIn);
|
|
|
|
int GetNoCount(int nVoteSignalIn);
|
|
|
|
int GetAbstainCount(int nVoteSignalIn);
|
2016-04-17 02:29:41 +02:00
|
|
|
|
|
|
|
void CleanAndRemove(bool fSignatureCheck);
|
|
|
|
void Relay();
|
|
|
|
|
|
|
|
uint256 GetHash(){
|
2016-05-13 18:03:01 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
uint256 nHashParent; //parent object, 0 is root
|
|
|
|
int nRevision; //object revision in the system
|
|
|
|
std::string strName; //org name, username, prop name, etc.
|
|
|
|
int64_t nTime; //time this object was created
|
|
|
|
uint256 nFeeTXHash; //fee-tx
|
|
|
|
*/
|
|
|
|
|
2016-04-17 02:29:41 +02:00
|
|
|
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
|
|
|
|
ss << strName;
|
2016-05-13 18:03:01 +02:00
|
|
|
ss << strData;
|
2016-04-17 02:29:41 +02:00
|
|
|
uint256 h1 = ss.GetHash();
|
|
|
|
|
|
|
|
return h1;
|
|
|
|
}
|
|
|
|
|
2016-04-15 11:10:38 +02:00
|
|
|
/**
|
2016-04-17 02:29:41 +02:00
|
|
|
* AddRegister - Example usage:
|
2016-04-16 19:19:17 +02:00
|
|
|
* --------------------------------------------------------
|
|
|
|
*
|
|
|
|
* We don't really care what's in these, as long as the masternode network
|
|
|
|
* believes they're accurate. Otherwise the masternodes will vote them down
|
|
|
|
* and we'll delete them from memory (fee-loss attack).
|
2016-04-15 11:10:38 +02:00
|
|
|
*
|
2016-04-16 19:19:17 +02:00
|
|
|
|
2016-04-15 11:10:38 +02:00
|
|
|
*/
|
|
|
|
|
2016-05-13 18:03:01 +02:00
|
|
|
bool SetData(std::string& strError, std::string strDataIn)
|
2016-04-16 19:19:17 +02:00
|
|
|
{
|
2016-05-13 18:03:01 +02:00
|
|
|
if(strDataIn.size() > 512*4)
|
2016-04-16 19:19:17 +02:00
|
|
|
{
|
|
|
|
strError = "Too big.";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-05-13 18:03:01 +02:00
|
|
|
strData = strDataIn;
|
2016-04-16 19:19:17 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-04-09 21:57:53 +02:00
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
|
|
|
|
template <typename Stream, typename Operation>
|
2016-04-17 02:29:41 +02:00
|
|
|
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion)
|
|
|
|
{
|
2016-04-26 06:08:36 +02:00
|
|
|
/**
|
|
|
|
* Store all major data items in serialization for other clients
|
|
|
|
* --
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* uint256 nHashParent; //parent object, 0 is root
|
|
|
|
* int nRevision; //object revision in the system
|
|
|
|
* std::string strName; //org name, username, prop name, etc.
|
|
|
|
* int64_t nTime; //time this object was created
|
|
|
|
* uint256 nFeeTXHash; //fee-tx
|
|
|
|
*
|
|
|
|
* // caching
|
|
|
|
* bool fValid;
|
|
|
|
* uint256 nHash;
|
|
|
|
*
|
|
|
|
* // Registers, these can be used for anything
|
|
|
|
* // -- check governance wiki for correct usage
|
|
|
|
* std::map<int, CGovernanceObjectRegister> mapRegister;
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
READWRITE(nHashParent);
|
|
|
|
READWRITE(nRevision);
|
|
|
|
READWRITE(LIMITED_STRING(strName, 64));
|
2016-04-09 21:57:53 +02:00
|
|
|
READWRITE(nTime);
|
|
|
|
READWRITE(nFeeTXHash);
|
2016-05-23 19:53:05 +02:00
|
|
|
READWRITE(strData);
|
2016-04-09 21:57:53 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|