neobytes/src/governance.h
Tim Flynn de7b2b6c51 Merge #944: V0.12.1.x governance pr - part 1 - base functionality
068c178 Added DBG macro in util.h to facilitate debugging

    - This macro allows debugging statements (typically printf's or cout's) to
      be activated or deactivated with a single comment.  Uncomment the line:
      //#define ENABLE_DASH_DEBUG
      in util.h to enable debugging statements.

    - When commented any code wrapped with the DBG() macro will simply be removed
      by the preprocessor.  When not commented all such wrapped statements will
      be present.

    - For maximum effectiveness it is best that util.h be the first effective include
      in all source files.  It is also possible to enable the macro for a single file
      by temporarily adding #define ENABLE_DASH_DEBUG to the top of the file.

    - Code committed to non-development branches should always have the define
      commented.

d125d9b V0.12.1.x -- merging trigger/generic object/superblock changes for testnet phase II

    - This commit contains the core governance system changes for 0.12.1.  Any unrelated
      changes have either been removed or moved to separate commits.

120724c File mode fixes

    - Changed mode 0755->0644 on several source files.

c7f9e11 Updated todo reminders

    - Added reminder to revert temporary reduction of number of votes
      required to trigger superblock to 1 for testing

92adc98 Made CSuperblockManager::IsValidSuperblockHeight an inline function

    - This is for efficiency since this function is called often and is
      only 1 line of code.

c050ed7 Added comment explaining rationale for no LOCK(cs) in CSuperblock::IsValid

dc933fe Removed unused CSuperblockManager::IsBlockValid function

decec88 Moved calls to SuperblockManager::IsValidSuperblockHeight into IsSuperblockTriggered.

    - Since calls to the later function are always protected by the former there's
      no reason to keep these separate and this simplifies the code in
      masternode-payments.cpp.

8672885 Reestablished expected value check for non-superblocks in IsBlockValueValid

b01cbe0 Changes to IsBlockValueValid to fix rpc test failure

a937c76 Changed include order to allow per file activation of the DBG macro

d116aa5 Fixed IsValidSuperblockHeight logic

    - Note this has an effect on testing because we can now only create
      1 superblock per day.  Devs may need to temporarily change testnet params
      for easier testing.

2d0c2de Convert superblock payments to CAmount

    - We assume that payment values in JSON are in units of DASH
      for consistency with other RPC functions, such as
      createrawtransaction.

376b833 Revert temporary testing value for nAbsVoteReq

    - Also ensure that number of votes required is never smaller than 1

8c89f4b Cleaned up CSuperblock error handling

    - Exceptions are now thrown consistently rather than using a mix of
      exceptions and return code checking.  Exceptions are now caught only
      in AddNewTrigger when the CSuperblock constructor is called.  Unnecessary object
      status members have been removed.

d7c8a6b Removed utilstrencodings header

    - This appears to help with travis tests, for unknown reasons.

c4dfc7a Fixed some minor code review issues

63c3580 Reverted locking change in miner.

    - This should have been done in the original PR but was overlooked.

4ab72de Fixed variable name to match common practice and bracket formatting

886a678 Improvements to vote conversion code

    - Replaced redundantly defined function with inclusion of governance-vote.h

    - Replaced magic numbers with their corresponding constant symbols

0a37966 Reordered governance message handling
2016-08-17 09:08:25 +02:00

308 lines
9.4 KiB
C++

// 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
//#define ENABLE_DASH_DEBUG
#include "util.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 "masternodeman.h"
#include <boost/lexical_cast.hpp>
#include "init.h"
#include <univalue.h>
#include "utilstrencodings.h"
#include <stdio.h>
#include <string.h>
using namespace std;
static const int GOVERNANCE_OBJECT_UNKNOWN = 0;
static const int GOVERNANCE_OBJECT_PROPOSAL = 1;
static const int GOVERNANCE_OBJECT_TRIGGER = 2;
extern CCriticalSection cs_budget;
class CGovernanceManager;
class CGovernanceObject;
class CGovernanceVote;
class CNode;
static const CAmount GOVERNANCE_FEE_TX = (0.1*COIN);
static const int64_t GOVERNANCE_FEE_CONFIRMATIONS = 1; //todo 12.1 -- easy testing
static const int64_t GOVERNANCE_UPDATE_MIN = 60*60;
extern std::map<uint256, int64_t> mapAskedForGovernanceObject;
extern CGovernanceManager governance;
// FOR SEEN MAP ARRAYS - GOVERNANCE OBJECTS AND VOTES
static const int SEEN_OBJECT_IS_VALID = 0;
static const int SEEN_OBJECT_ERROR_INVALID = 1;
static const int SEEN_OBJECT_ERROR_IMMATURE = 2;
static const int SEEN_OBJECT_EXECUTED = 3; //used for triggers
static const int SEEN_OBJECT_UNKNOWN = 4; // the default
//Check the collateral transaction for the budget proposal/finalized budget
extern bool IsCollateralValid(uint256 nTxCollateralHash, uint256 nExpectedHash, std::string& strError, int& nConf, CAmount minFee);
//
// Governance Manager : Contains all proposals for the budget
//
class CGovernanceManager
{
public: // Types
typedef std::map<uint256, CGovernanceObject> object_m_t;
typedef object_m_t::iterator object_m_it;
typedef object_m_t::const_iterator object_m_cit;
typedef std::map<uint256, int> count_m_t;
typedef count_m_t::iterator count_m_it;
typedef count_m_t::const_iterator count_m_cit;
typedef std::map<uint256, CGovernanceVote> vote_m_t;
typedef vote_m_t::iterator vote_m_it;
typedef vote_m_t::const_iterator vote_m_cit;
typedef std::map<uint256, CTransaction> transaction_m_t;
typedef transaction_m_t::iterator transaction_m_it;
typedef transaction_m_t::const_iterator transaction_m_cit;
typedef object_m_t::size_type size_type;
private:
//hold txes until they mature enough to use
transaction_m_t mapCollateral;
// Keep track of current block index
const CBlockIndex *pCurrentBlockIndex;
int64_t nTimeLastDiff;
int nCachedBlockHeight;
// keep track of the scanning errors
object_m_t mapObjects;
// note: move to private for better encapsulation
count_m_t mapSeenGovernanceObjects;
count_m_t mapSeenVotes;
vote_m_t mapOrphanVotes;
// todo: one of these should point to the other
// -- must be carefully managed while adding/removing/updating
vote_m_t mapVotesByHash;
vote_m_t mapVotesByType;
public:
// critical section to protect the inner data structures
mutable CCriticalSection cs;
CGovernanceManager()
: mapCollateral(),
pCurrentBlockIndex(NULL),
nTimeLastDiff(0),
nCachedBlockHeight(0),
mapObjects(),
cs()
{}
void ClearSeen() {
LOCK(cs);
mapSeenGovernanceObjects.clear();
mapSeenVotes.clear();
}
int CountProposalInventoryItems()
{
return mapSeenGovernanceObjects.size() + mapSeenVotes.size();
}
int sizeProposals() {return (int)mapObjects.size();}
void Sync(CNode* node, uint256 nProp);
void SyncParentObjectByVote(CNode* pfrom, const CGovernanceVote& vote);
void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
void NewBlock();
CGovernanceObject *FindGovernanceObject(const std::string &strName);
CGovernanceObject *FindGovernanceObject(const uint256& nHash);
std::vector<CGovernanceVote*> GetMatchingVotes(const uint256& nParentHash);
std::vector<CGovernanceObject*> GetAllNewerThan(int64_t nMoreThanTime);
int CountMatchingVotes(CGovernanceObject& govobj, int nVoteSignalIn, int nVoteOutcomeIn);
bool IsBudgetPaymentBlock(int nBlockHeight);
bool AddGovernanceObject (CGovernanceObject& govobj);
bool AddOrUpdateVote(const CGovernanceVote& vote, CNode* pfrom, std::string& strError);
std::string GetRequiredPaymentsString(int nBlockHeight);
void CleanAndRemove(bool fSignatureCheck);
void UpdateCachesAndClean();
void CheckAndRemove() {UpdateCachesAndClean();}
void CheckOrphanVotes();
void Clear(){
LOCK(cs);
LogPrint("gobject", "Governance object manager was cleared\n");
mapObjects.clear();
mapSeenGovernanceObjects.clear();
mapSeenVotes.clear();
mapOrphanVotes.clear();
mapVotesByType.clear();
mapVotesByHash.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) {
LOCK(cs);
READWRITE(mapSeenGovernanceObjects);
READWRITE(mapSeenVotes);
READWRITE(mapOrphanVotes);
READWRITE(mapObjects);
READWRITE(mapVotesByHash);
READWRITE(mapVotesByType);
}
void UpdatedBlockTip(const CBlockIndex *pindex);
int64_t GetLastDiffTime() {return nTimeLastDiff;}
void UpdateLastDiffTime(int64_t nTimeIn) {nTimeLastDiff=nTimeIn;}
int GetCachedBlockHeight() { return nCachedBlockHeight; }
// Accessors for thread-safe access to maps
bool HaveObjectForHash(uint256 nHash);
bool HaveVoteForHash(uint256 nHash);
// int GetVoteCountByHash(uint256 nHash);
bool SerializeObjectForHash(uint256 nHash, CDataStream& ss);
bool SerializeVoteForHash(uint256 nHash, CDataStream& ss);
void AddSeenGovernanceObject(uint256 nHash, int status);
void AddSeenVote(uint256 nHash, int status);
};
/**
* Governance Object
*
*/
class CGovernanceObject
{
private:
// critical section to protect the inner data structures
mutable CCriticalSection cs;
public:
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 nCollateralHash; //fee-tx
std::string strData; // Data field - can be used for anything
int nObjectType;
bool fCachedLocalValidity; // is valid by blockchain
std::string strLocalValidityError;
// VARIOUS FLAGS FOR OBJECT / SET VIA MASTERNODE VOTING
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
bool fUnparsable; // data field was unparsible, object will be rejected
bool fExpired; // Object is no longer of interest
CGovernanceObject();
CGovernanceObject(uint256 nHashParentIn, int nRevisionIn, std::string strNameIn, int64_t nTime, uint256 nCollateralHashIn, std::string strDataIn);
CGovernanceObject(const CGovernanceObject& other);
void swap(CGovernanceObject& first, CGovernanceObject& second); // nothrow
// CORE OBJECT FUNCTIONS
bool IsValidLocally(const CBlockIndex* pindex, std::string& strError, bool fCheckCollateral);
void UpdateLocalValidity(const CBlockIndex *pCurrentBlockIndex);
void UpdateSentinelVariables(const CBlockIndex *pCurrentBlockIndex);
int GetObjectType();
int GetObjectSubtype();
std::string GetName() {return strName; }
UniValue GetJSONObject();
void Relay();
uint256 GetHash();
// GET VOTE COUNT FOR SIGNAL
int GetAbsoluteYesCount(int nVoteSignalIn);
int GetAbsoluteNoCount(int nVoteSignalIn);
int GetYesCount(int nVoteSignalIn);
int GetNoCount(int nVoteSignalIn);
int GetAbstainCount(int nVoteSignalIn);
// FUNCTIONS FOR DEALING WITH DATA STRING
void LoadData();
bool SetData(std::string& strError, std::string strDataIn);
bool GetData(UniValue& objResult);
std::string GetDataAsHex();
std::string GetDataAsString();
// SERIALIZER
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion)
{
// SERIALIZE DATA FOR SAVING/LOADING OR NETWORK FUNCTIONS
READWRITE(nHashParent);
READWRITE(nRevision);
READWRITE(LIMITED_STRING(strName, 64));
READWRITE(nTime);
READWRITE(nCollateralHash);
READWRITE(strData);
READWRITE(nObjectType);
// AFTER DESERIALIZATION OCCURS, CACHED VARIABLES MUST BE CALCULATED MANUALLY
}
};
#endif