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-05-25 18:56:58 +02:00
# include "masternodeman.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-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
2016-05-23 20:16:46 +02:00
static const CAmount GOVERNANCE_FEE_TX = ( 0.1 * COIN ) ;
2016-04-10 02:43:15 +02:00
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-05-23 20:10:20 +02:00
extern std : : vector < CGovernanceObject > vecImmatureGovernanceObjects ;
extern std : : map < uint256 , int64_t > mapAskedForGovernanceObject ;
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-05-31 22:00:01 +02:00
extern bool IsCollateralValid ( uint256 nTxCollateralHash , uint256 nExpectedHash , std : : string & strError , 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 ;
2016-05-23 19:58:39 +02:00
std : : map < uint256 , CGovernanceVote > mapOrphanVotes ;
2016-06-08 08:57:16 +02:00
// todo: one of these should point to the other
// -- must be carefully managed while adding/removing/updating
std : : map < uint256 , CGovernanceVote > mapVotesByHash ;
std : : map < uint256 , CGovernanceVote > mapVotesByType ;
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-06-08 08:57:16 +02:00
void SyncParentObjectByVote ( CNode * pfrom , const CGovernanceVote & vote ) ;
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-05-24 20:11:59 +02:00
CGovernanceObject * FindGovernanceObject ( const std : : string & strName ) ;
2016-06-08 08:57:16 +02:00
CGovernanceObject * FindGovernanceObject ( const 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 23:39:10 +02:00
int CountMatchingVotes ( CGovernanceObject & govobj , int nVoteSignalIn , int nVoteOutcomeIn ) ;
2016-05-23 19:53:05 +02:00
2016-04-09 21:57:53 +02:00
bool IsBudgetPaymentBlock ( int nBlockHeight ) ;
2016-05-28 12:31:44 +02:00
bool AddGovernanceObject ( CGovernanceObject & govobj ) ;
2016-06-08 08:57:16 +02:00
bool UpdateGovernanceObject ( const CGovernanceVote & vote , CNode * pfrom , std : : string & strError ) ;
bool AddOrUpdateVote ( const CGovernanceVote & vote , std : : string & strError ) ;
2016-04-09 21:57:53 +02:00
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 ) ;
2016-05-23 23:39:10 +02:00
LogPrintf ( " Governance object manager was 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-05-23 19:58:39 +02:00
mapOrphanVotes . clear ( ) ;
2016-06-08 08:57:16 +02:00
mapVotesByType . clear ( ) ;
mapVotesByHash . clear ( ) ;
2016-04-09 21:57:53 +02:00
}
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-05-23 19:58:39 +02:00
READWRITE ( mapOrphanVotes ) ;
2016-05-13 18:03:01 +02:00
READWRITE ( mapObjects ) ;
2016-06-08 08:57:16 +02:00
READWRITE ( mapVotesByHash ) ;
READWRITE ( mapVotesByType ) ;
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-23 23:39:10 +02:00
// set by IsValid()
bool fCachedLocalValidity ;
std : : string strLocalValidityError ;
// set via sentinel voting mechanisms
2016-06-10 07:16:32 +02:00
// caching -- one per voting mechanism -- see below for more information
bool fCachedFunding ; // true == minimum network support has been reached for this object to be funded (doesn't mean it will for sure though)
bool fCachedValid ; // true == minimum network has been reached flagging this object as a valid and understood goverance object (e.g, the serialized data is correct format, etc)
bool fCachedDelete ; // true == minimum network support has been reached saying this object should be deleted from the system entirely
bool fCachedEndorsed ; // true == minimum network support has been reached flagging this object as endorsed by an elected representative body (e.g. business review board / technecial review board /etc)
// bool fDirtyCache; // object was updated and cached values should be updated soon
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-05-23 23:39:10 +02:00
// Update local validity : store the values in memory
void UpdateLocalValidity ( const CBlockIndex * pCurrentBlockIndex ) { fCachedLocalValidity = IsValid ( pCurrentBlockIndex , strLocalValidityError ) ; } ;
2016-05-24 20:11:59 +02:00
void UpdateSentinelVariables ( const CBlockIndex * pCurrentBlockIndex )
2016-05-24 00:52:10 +02:00
{
2016-05-27 00:03:37 +02:00
// CALCULATE MINIMUM SUPPORT LEVELS REQUIRED
2016-05-24 00:52:10 +02:00
2016-05-24 20:11:59 +02:00
int nMnCount = mnodeman . CountEnabled ( ) ;
2016-06-08 08:57:16 +02:00
if ( nMnCount = = 0 ) return ;
// CALCULATE THE MINUMUM VOTE COUNT REQUIRED FOR FULL SIGNAL
2016-05-24 20:11:59 +02:00
int nAbsYesVoteReq = nMnCount / 10 ;
2016-06-08 08:57:16 +02:00
int nAbsNoVoteReq = nAbsYesVoteReq ; //same in absolute value
2016-05-24 00:52:10 +02:00
2016-05-27 00:03:37 +02:00
// SET SENTINEL FLAGS TO FALSE
2016-05-24 20:11:59 +02:00
fCachedFunding = false ;
2016-06-08 08:57:16 +02:00
fCachedValid = true ; //default to valid
2016-05-24 20:11:59 +02:00
fCachedDelete = false ;
fCachedEndorsed = false ;
2016-05-27 00:03:37 +02:00
// SET SENTINEL FLAGS TO TRUE IF MIMIMUM SUPPORT LEVELS ARE REACHED
2016-06-08 08:57:16 +02:00
// todo - 12.1
// if(GetAbsoluteYesCount(VOTE_SIGNAL_FUNDING) >= nAbsYesVoteReq) fCachedFunding = true;
// if(GetAbsoluteYesCount(VOTE_SIGNAL_VALID) >= nAbsYesVoteReq) fCachedValid = true;
// if(GetAbsoluteYesCount(VOTE_SIGNAL_DELETE) >= nAbsYesVoteReq) fCachedDelete = true;
// if(GetAbsoluteYesCount(VOTE_SIGNAL_ENDORSED) >= nAbsYesVoteReq) fCachedEndorsed = true;
// if(GetAbsoluteNoCount(VOTE_SIGNAL_FUNDING) >= nAbsNoVoteReq) fCachedFunding = false;
// if(GetAbsoluteNoCount(VOTE_SIGNAL_VALID) >= nAbsNoVoteReq) fCachedValid = false;
// if(GetAbsoluteNoCount(VOTE_SIGNAL_DELETE) >= nAbsNoVoteReq) fCachedDelete = false;
// if(GetAbsoluteNoCount(VOTE_SIGNAL_ENDORSED) >= nAbsNoVoteReq) fCachedEndorsed = false;
2016-05-24 00:52:10 +02:00
}
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 . fCachedEndorsed , second . fCachedEndorsed ) ;
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 ) ;
2016-06-08 08:57:16 +02:00
int GetAbsoluteNoCount ( int nVoteSignalIn ) ;
2016-05-23 19:53:05 +02:00
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
2016-05-27 00:03:37 +02:00
// CREATE HASH OF ALL IMPORTANT PIECES OF DATA
2016-05-13 18:03:01 +02:00
2016-04-17 02:29:41 +02:00
CHashWriter ss ( SER_GETHASH , PROTOCOL_VERSION ) ;
2016-05-24 00:52:10 +02:00
ss < < nHashParent ;
ss < < nRevision ;
2016-04-17 02:29:41 +02:00
ss < < strName ;
2016-05-24 00:52:10 +02:00
ss < < nTime ;
2016-05-13 18:03:01 +02:00
ss < < strData ;
2016-05-27 00:03:37 +02:00
// fee_tx is left out on purpose
2016-04-17 02:29:41 +02:00
uint256 h1 = ss . GetHash ( ) ;
return h1 ;
}
2016-04-15 11:10:38 +02:00
/**
2016-05-27 00:03:37 +02:00
* SetData - Example usage :
2016-04-16 19:19:17 +02:00
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
2016-06-08 08:57:16 +02:00
* Governance is data - agnostic , for rules about data see sentinel documentation
2016-05-27 00:03:37 +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-27 00:03:37 +02:00
// SET DATA FIELD TO INPUT
2016-05-13 18:03:01 +02:00
if ( strDataIn . size ( ) > 512 * 4 )
2016-04-16 19:19:17 +02:00
{
2016-05-27 00:03:37 +02:00
// (assumption) this is equal to pythons len(strData) > 512*4, I think
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-05-27 00:03:37 +02:00
// SERIALIZE DATA FOR SAVING/LOADING OR NETWORK FUNCTIONS
2016-04-26 06:08:36 +02:00
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-06-10 07:16:32 +02:00
// AFTER DESERIALIZATION OCCURS, CACHED VARIABLES MUST BE CALCULATED MANUALLY
2016-04-09 21:57:53 +02:00
}
} ;
# endif