dash/src/governance/governance-object.h

359 lines
9.8 KiB
C
Raw Normal View History

// Copyright (c) 2014-2019 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 GOVERNANCE_OBJECT_H
#define GOVERNANCE_OBJECT_H
#include "cachemultimap.h"
#include "governance-exceptions.h"
#include "governance-vote.h"
#include "governance-votedb.h"
#include "key.h"
#include "net.h"
#include "sync.h"
#include "util.h"
#include "utilstrencodings.h"
#include "bls/bls.h"
#include <univalue.h>
class CGovernanceManager;
class CGovernanceTriggerManager;
class CGovernanceObject;
class CGovernanceVote;
static const int MIN_GOVERNANCE_PEER_PROTO_VERSION = 70213;
static const int GOVERNANCE_FILTER_PROTO_VERSION = 70206;
static const int GOVERNANCE_POSE_BANNED_VOTES_VERSION = 70215;
static const double GOVERNANCE_FILTER_FP_RATE = 0.001;
static const int GOVERNANCE_OBJECT_UNKNOWN = 0;
static const int GOVERNANCE_OBJECT_PROPOSAL = 1;
static const int GOVERNANCE_OBJECT_TRIGGER = 2;
static const CAmount GOVERNANCE_PROPOSAL_FEE_TX = (5.0 * COIN);
static const int64_t GOVERNANCE_FEE_CONFIRMATIONS = 6;
static const int64_t GOVERNANCE_MIN_RELAY_FEE_CONFIRMATIONS = 1;
static const int64_t GOVERNANCE_UPDATE_MIN = 60 * 60;
static const int64_t GOVERNANCE_DELETION_DELAY = 10 * 60;
static const int64_t GOVERNANCE_ORPHAN_EXPIRATION_TIME = 10 * 60;
// 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
typedef std::pair<CGovernanceVote, int64_t> vote_time_pair_t;
inline bool operator<(const vote_time_pair_t& p1, const vote_time_pair_t& p2)
{
return (p1.first < p2.first);
}
struct vote_instance_t {
vote_outcome_enum_t eOutcome;
int64_t nTime;
int64_t nCreationTime;
vote_instance_t(vote_outcome_enum_t eOutcomeIn = VOTE_OUTCOME_NONE, int64_t nTimeIn = 0, int64_t nCreationTimeIn = 0) :
eOutcome(eOutcomeIn),
nTime(nTimeIn),
nCreationTime(nCreationTimeIn)
{
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
{
int nOutcome = int(eOutcome);
READWRITE(nOutcome);
READWRITE(nTime);
READWRITE(nCreationTime);
if (ser_action.ForRead()) {
eOutcome = vote_outcome_enum_t(nOutcome);
}
}
};
typedef std::map<int, vote_instance_t> vote_instance_m_t;
typedef vote_instance_m_t::iterator vote_instance_m_it;
typedef vote_instance_m_t::const_iterator vote_instance_m_cit;
struct vote_rec_t {
vote_instance_m_t mapInstances;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
{
READWRITE(mapInstances);
}
};
/**
* Governance Object
*
*/
class CGovernanceObject
{
friend class CGovernanceManager;
friend class CGovernanceTriggerManager;
friend class CSuperblock;
public: // Types
typedef std::map<COutPoint, vote_rec_t> vote_m_t;
typedef vote_m_t::iterator vote_m_it;
typedef vote_m_t::const_iterator vote_m_cit;
typedef CacheMultiMap<COutPoint, vote_time_pair_t> vote_cmm_t;
private:
/// critical section to protect the inner data structures
mutable CCriticalSection cs;
/// Object typecode
int nObjectType;
/// parent object, 0 is root
uint256 nHashParent;
/// object revision in the system
int nRevision;
/// time this object was created
int64_t nTime;
/// time this object was marked for deletion
int64_t nDeletionTime;
/// fee-tx
uint256 nCollateralHash;
/// Data field - can be used for anything
std::vector<unsigned char> vchData;
/// Masternode info for signed objects
COutPoint masternodeOutpoint;
std::vector<unsigned char> vchSig;
/// is valid by blockchain
bool fCachedLocalValidity;
std::string strLocalValidityError;
// VARIOUS FLAGS FOR OBJECT / SET VIA MASTERNODE VOTING
/// true == minimum network support has been reached for this object to be funded (doesn't mean it will for sure though)
bool fCachedFunding;
/// true == minimum network has been reached flagging this object as a valid and understood governance object (e.g, the serialized data is correct format, etc)
bool fCachedValid;
/// true == minimum network support has been reached saying this object should be deleted from the system entirely
bool fCachedDelete;
/** 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 fCachedEndorsed;
/// object was updated and cached values should be updated soon
bool fDirtyCache;
/// Object is no longer of interest
bool fExpired;
/// Failed to parse object data
bool fUnparsable;
vote_m_t mapCurrentMNVotes;
/// Limited map of votes orphaned by MN
vote_cmm_t cmmapOrphanVotes;
CGovernanceObjectVoteFile fileVotes;
public:
CGovernanceObject();
CGovernanceObject(const uint256& nHashParentIn, int nRevisionIn, int64_t nTime, const uint256& nCollateralHashIn, const std::string& strDataHexIn);
CGovernanceObject(const CGovernanceObject& other);
// Public Getter methods
int64_t GetCreationTime() const
{
return nTime;
}
int64_t GetDeletionTime() const
{
return nDeletionTime;
}
int GetObjectType() const
{
return nObjectType;
}
const uint256& GetCollateralHash() const
{
return nCollateralHash;
}
const COutPoint& GetMasternodeOutpoint() const
{
return masternodeOutpoint;
}
bool IsSetCachedFunding() const
{
return fCachedFunding;
}
bool IsSetCachedValid() const
{
return fCachedValid;
}
bool IsSetCachedDelete() const
{
return fCachedDelete;
}
bool IsSetCachedEndorsed() const
{
return fCachedEndorsed;
}
bool IsSetDirtyCache() const
{
return fDirtyCache;
}
bool IsSetExpired() const
{
return fExpired;
}
const CGovernanceObjectVoteFile& GetVoteFile() const
{
return fileVotes;
}
// Signature related functions
void SetMasternodeOutpoint(const COutPoint& outpoint);
bool Sign(const CBLSSecretKey& key);
bool CheckSignature(const CBLSPublicKey& pubKey) const;
std::string GetSignatureMessage() const;
uint256 GetSignatureHash() const;
// CORE OBJECT FUNCTIONS
bool IsValidLocally(std::string& strError, bool fCheckCollateral) const;
bool IsValidLocally(std::string& strError, bool& fMissingMasternode, bool& fMissingConfirmations, bool fCheckCollateral) const;
/// Check the collateral transaction for the budget proposal/finalized budget
bool IsCollateralValid(std::string& strError, bool& fMissingConfirmations) const;
void UpdateLocalValidity();
void UpdateSentinelVariables();
CAmount GetMinCollateralFee() const;
UniValue GetJSONObject();
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
void Relay(CConnman& connman);
uint256 GetHash() const;
// GET VOTE COUNT FOR SIGNAL
int CountMatchingVotes(vote_signal_enum_t eVoteSignalIn, vote_outcome_enum_t eVoteOutcomeIn) const;
int GetAbsoluteYesCount(vote_signal_enum_t eVoteSignalIn) const;
int GetAbsoluteNoCount(vote_signal_enum_t eVoteSignalIn) const;
int GetYesCount(vote_signal_enum_t eVoteSignalIn) const;
int GetNoCount(vote_signal_enum_t eVoteSignalIn) const;
int GetAbstainCount(vote_signal_enum_t eVoteSignalIn) const;
bool GetCurrentMNVotes(const COutPoint& mnCollateralOutpoint, vote_rec_t& voteRecord) const;
// FUNCTIONS FOR DEALING WITH DATA STRING
std::string GetDataAsHexString() const;
std::string GetDataAsPlainString() const;
// SERIALIZER
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
{
// SERIALIZE DATA FOR SAVING/LOADING OR NETWORK FUNCTIONS
READWRITE(nHashParent);
READWRITE(nRevision);
READWRITE(nTime);
READWRITE(nCollateralHash);
READWRITE(vchData);
READWRITE(nObjectType);
READWRITE(masternodeOutpoint);
if (!(s.GetType() & SER_GETHASH)) {
READWRITE(vchSig);
}
if (s.GetType() & SER_DISK) {
// Only include these for the disk file format
Backport Bitcoin#9424, Bitcoin#10123 and Bitcoin#10153 (#2918) * Contains dashification. disables `-debug dash` Merge #9424: Change LogAcceptCategory to use uint32_t rather than sets of strings. 6b3bb3d Change LogAcceptCategory to use uint32_t rather than sets of strings. (Gregory Maxwell) Tree-SHA512: ebb5bcf9a7d00a32dd1390b727ff4d29330a038423611da01268d8e1d2c0229e52a1098e751d4e6db73ef4ae862e1e96d38249883fcaf12b68f55ebb01035b34 Signed-off-by: Pasta <Pasta@dash.org> 31 -> 32 Signed-off-by: Pasta <Pasta@dash.org> * Merge #10123: Allow debug logs to be excluded from specified component 3bde556 Add -debugexclude option to switch off logging for specified components (John Newbery) Tree-SHA512: 30202e3f2085fc2fc5dd4bedb92988f4cb162c612a42cf8f6395a7da326f34975ddc347f82bc4ddca6c84c438dc0cc6e87869f90c7ff88105dbeaa52a947fa43 * bump to uint64_t due to added Dash codes Signed-off-by: Pasta <Pasta@dash.org> * bump to uint64_t due to added Dash codes cont. Signed-off-by: Pasta <Pasta@dash.org> * string -> BCLog format Signed-off-by: Pasta <Pasta@dash.org> * uint32_t -> uint64_t Signed-off-by: Pasta <Pasta@dash.org> * Fix CBatchedLogger * Fix most fDebug-s * Fix `debug` rpc * Fix BENCH and RAND conflicts * Add ALERT and use it * Update LogPrint-s in dash-specific code * Tweak few log categories Specifically: - use PRIVATESEND in `CPrivateSendClientManager::GetRandomNotUsedMasternode()` - use ZMQ in `CZMQPublishRawGovernanceVoteNotifier::NotifyGovernanceVote()` and `CZMQPublishRawGovernanceObjectNotifier::NotifyGovernanceObject()` * Drop no longer used MASTERNODE category * Merge #10153: logging: Fix off-by-one for shrinkdebugfile default faab624 logging: Fix off-by-one for shrinkdebugfile (MarcoFalke) Tree-SHA512: d6153e06067906172ff0611af9e585a3ecf0a7d56925b6ad7c12e75aa802441047059b9b6f6c78e79916c3f2abc8f1998bfd2d5b84201ec6421f727c08da3c21 * Shift dash-specific log categories to start from `1ul << 32` to avoid potential future conflicts with bitcoin ones * Fix `dash` category * remove debugCategories Signed-off-by: Pasta <Pasta@dash.org> * Prepend "std::" to find call * Check for BCLog::PRIVATESEND instead of logCategories != BCLog::NONE * Use BCLog::MNPAYMENTS category instead of checking for logCategories != BCLog::NONE * Move "End Dash" comment below "ALERT" When adding new entries here, we'll otherwise get confused with ordering and might end up forgetting that adding something Dash specific must continue with the bit after 43.
2019-05-22 23:51:39 +02:00
LogPrint(BCLog::GOBJECT, "CGovernanceObject::SerializationOp Reading/writing votes from/to disk\n");
READWRITE(nDeletionTime);
READWRITE(fExpired);
READWRITE(mapCurrentMNVotes);
READWRITE(fileVotes);
Backport Bitcoin#9424, Bitcoin#10123 and Bitcoin#10153 (#2918) * Contains dashification. disables `-debug dash` Merge #9424: Change LogAcceptCategory to use uint32_t rather than sets of strings. 6b3bb3d Change LogAcceptCategory to use uint32_t rather than sets of strings. (Gregory Maxwell) Tree-SHA512: ebb5bcf9a7d00a32dd1390b727ff4d29330a038423611da01268d8e1d2c0229e52a1098e751d4e6db73ef4ae862e1e96d38249883fcaf12b68f55ebb01035b34 Signed-off-by: Pasta <Pasta@dash.org> 31 -> 32 Signed-off-by: Pasta <Pasta@dash.org> * Merge #10123: Allow debug logs to be excluded from specified component 3bde556 Add -debugexclude option to switch off logging for specified components (John Newbery) Tree-SHA512: 30202e3f2085fc2fc5dd4bedb92988f4cb162c612a42cf8f6395a7da326f34975ddc347f82bc4ddca6c84c438dc0cc6e87869f90c7ff88105dbeaa52a947fa43 * bump to uint64_t due to added Dash codes Signed-off-by: Pasta <Pasta@dash.org> * bump to uint64_t due to added Dash codes cont. Signed-off-by: Pasta <Pasta@dash.org> * string -> BCLog format Signed-off-by: Pasta <Pasta@dash.org> * uint32_t -> uint64_t Signed-off-by: Pasta <Pasta@dash.org> * Fix CBatchedLogger * Fix most fDebug-s * Fix `debug` rpc * Fix BENCH and RAND conflicts * Add ALERT and use it * Update LogPrint-s in dash-specific code * Tweak few log categories Specifically: - use PRIVATESEND in `CPrivateSendClientManager::GetRandomNotUsedMasternode()` - use ZMQ in `CZMQPublishRawGovernanceVoteNotifier::NotifyGovernanceVote()` and `CZMQPublishRawGovernanceObjectNotifier::NotifyGovernanceObject()` * Drop no longer used MASTERNODE category * Merge #10153: logging: Fix off-by-one for shrinkdebugfile default faab624 logging: Fix off-by-one for shrinkdebugfile (MarcoFalke) Tree-SHA512: d6153e06067906172ff0611af9e585a3ecf0a7d56925b6ad7c12e75aa802441047059b9b6f6c78e79916c3f2abc8f1998bfd2d5b84201ec6421f727c08da3c21 * Shift dash-specific log categories to start from `1ul << 32` to avoid potential future conflicts with bitcoin ones * Fix `dash` category * remove debugCategories Signed-off-by: Pasta <Pasta@dash.org> * Prepend "std::" to find call * Check for BCLog::PRIVATESEND instead of logCategories != BCLog::NONE * Use BCLog::MNPAYMENTS category instead of checking for logCategories != BCLog::NONE * Move "End Dash" comment below "ALERT" When adding new entries here, we'll otherwise get confused with ordering and might end up forgetting that adding something Dash specific must continue with the bit after 43.
2019-05-22 23:51:39 +02:00
LogPrint(BCLog::GOBJECT, "CGovernanceObject::SerializationOp hash = %s, vote count = %d\n", GetHash().ToString(), fileVotes.GetVoteCount());
}
// AFTER DESERIALIZATION OCCURS, CACHED VARIABLES MUST BE CALCULATED MANUALLY
}
private:
// FUNCTIONS FOR DEALING WITH DATA STRING
void LoadData();
void GetData(UniValue& objResult);
bool ProcessVote(CNode* pfrom,
const CGovernanceVote& vote,
CGovernanceException& exception,
CConnman& connman);
/// Called when MN's which have voted on this object have been removed
void ClearMasternodeVotes();
// Revalidate all votes from this MN and delete them if validation fails.
// This is the case for DIP3 MNs that changed voting or operator keys and
// also for MNs that were removed from the list completely.
// Returns deleted vote hashes.
std::set<uint256> RemoveInvalidVotes(const COutPoint& mnOutpoint);
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
void CheckOrphanVotes(CConnman& connman);
};
#endif