Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

governance-vote.cpp
Go to the documentation of this file.
1 // Copyright (c) 2014-2019 The Dash Core developers
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
8 #include <messagesigner.h>
9 #include <spork.h>
10 #include <util.h>
11 
12 #include <evo/deterministicmns.h>
13 
15 {
16  static const std::map<vote_outcome_enum_t, std::string> mapOutcomeString = {
17  { VOTE_OUTCOME_NONE, "none" },
18  { VOTE_OUTCOME_YES, "yes" },
19  { VOTE_OUTCOME_NO, "no" },
20  { VOTE_OUTCOME_ABSTAIN, "abstain" } };
21 
22  const auto& it = mapOutcomeString.find(nOutcome);
23  if (it == mapOutcomeString.end()) {
24  LogPrintf("CGovernanceVoting::%s -- ERROR: Unknown outcome %d\n", __func__, nOutcome);
25  return "error";
26  }
27  return it->second;
28 }
29 
31 {
32  static const std::map<vote_signal_enum_t, std::string> mapSignalsString = {
33  { VOTE_SIGNAL_FUNDING, "funding" },
34  { VOTE_SIGNAL_VALID, "valid" },
35  { VOTE_SIGNAL_DELETE, "delete" },
36  { VOTE_SIGNAL_ENDORSED, "endorsed" } };
37 
38  const auto& it = mapSignalsString.find(nSignal);
39  if (it == mapSignalsString.end()) {
40  LogPrintf("CGovernanceVoting::%s -- ERROR: Unknown signal %d\n", __func__, nSignal);
41  return "none";
42  }
43  return it->second;
44 }
45 
46 
48 {
49  static const std::map<std::string, vote_outcome_enum_t> mapStringOutcome = {
50  { "none", VOTE_OUTCOME_NONE },
51  { "yes", VOTE_OUTCOME_YES },
52  { "no", VOTE_OUTCOME_NO },
53  { "abstain", VOTE_OUTCOME_ABSTAIN } };
54 
55  const auto& it = mapStringOutcome.find(strVoteOutcome);
56  if (it == mapStringOutcome.end()) {
57  LogPrintf("CGovernanceVoting::%s -- ERROR: Unknown outcome %s\n", __func__, strVoteOutcome);
58  return VOTE_OUTCOME_NONE;
59  }
60  return it->second;
61 
62 }
63 
65 {
66  static const std::map<std::string, vote_signal_enum_t> mapStrVoteSignals = {
67  {"funding", VOTE_SIGNAL_FUNDING},
68  {"valid", VOTE_SIGNAL_VALID},
69  {"delete", VOTE_SIGNAL_DELETE},
70  {"endorsed", VOTE_SIGNAL_ENDORSED}};
71 
72  const auto& it = mapStrVoteSignals.find(strVoteSignal);
73  if (it == mapStrVoteSignals.end()) {
74  LogPrintf("CGovernanceVoting::%s -- ERROR: Unknown signal %s\n", __func__, strVoteSignal);
75  return VOTE_SIGNAL_NONE;
76  }
77  return it->second;
78 }
79 
81  fValid(true),
82  fSynced(false),
83  nVoteSignal(int(VOTE_SIGNAL_NONE)),
84  masternodeOutpoint(),
85  nParentHash(),
86  nVoteOutcome(int(VOTE_OUTCOME_NONE)),
87  nTime(0),
88  vchSig()
89 {
90 }
91 
92 CGovernanceVote::CGovernanceVote(const COutPoint& outpointMasternodeIn, const uint256& nParentHashIn, vote_signal_enum_t eVoteSignalIn, vote_outcome_enum_t eVoteOutcomeIn) :
93  fValid(true),
94  fSynced(false),
95  nVoteSignal(eVoteSignalIn),
96  masternodeOutpoint(outpointMasternodeIn),
97  nParentHash(nParentHashIn),
98  nVoteOutcome(eVoteOutcomeIn),
99  nTime(GetAdjustedTime()),
100  vchSig()
101 {
102  UpdateHash();
103 }
104 
105 std::string CGovernanceVote::ToString() const
106 {
107  std::ostringstream ostr;
108  ostr << masternodeOutpoint.ToStringShort() << ":"
109  << nTime << ":"
112  return ostr.str();
113 }
114 
115 void CGovernanceVote::Relay(CConnman& connman) const
116 {
117  // Do not relay until fully synced
118  if (!masternodeSync.IsSynced()) {
119  LogPrint(BCLog::GOBJECT, "CGovernanceVote::Relay -- won't relay until fully synced\n");
120  return;
121  }
122 
123  auto mnList = deterministicMNManager->GetListAtChainTip();
124  auto dmn = mnList.GetMNByCollateral(masternodeOutpoint);
125  if (!dmn) {
126  return;
127  }
128 
129  // When this vote is from non-valid (PoSe banned) MN, we should only announce it to v0.14.0.1 nodes as older nodes
130  // will ban us otherwise.
131  int minVersion = MIN_GOVERNANCE_PEER_PROTO_VERSION;
132  if (!mnList.IsMNValid(dmn)) {
134  }
135 
137  connman.RelayInv(inv, minVersion);
138 }
139 
141 {
142  // Note: doesn't match serialization
143 
145  ss << masternodeOutpoint << uint8_t{} << 0xffffffff; // adding dummy values here to match old hashing format
146  ss << nParentHash;
147  ss << nVoteSignal;
148  ss << nVoteOutcome;
149  ss << nTime;
150  *const_cast<uint256*>(&hash) = ss.GetHash();
151 }
152 
154 {
155  return hash;
156 }
157 
159 {
160  return SerializeHash(*this);
161 }
162 
163 bool CGovernanceVote::Sign(const CKey& key, const CKeyID& keyID)
164 {
165  std::string strError;
166 
167  // Harden Spork6 so that it is active on testnet and no other networks
168  if (Params().NetworkIDString() == CBaseChainParams::TESTNET) {
170 
171  if (!CHashSigner::SignHash(hash, key, vchSig)) {
172  LogPrintf("CGovernanceVote::Sign -- SignHash() failed\n");
173  return false;
174  }
175 
176  if (!CHashSigner::VerifyHash(hash, keyID, vchSig, strError)) {
177  LogPrintf("CGovernanceVote::Sign -- VerifyHash() failed, error: %s\n", strError);
178  return false;
179  }
180  } else {
181  std::string strMessage = masternodeOutpoint.ToStringShort() + "|" + nParentHash.ToString() + "|" +
182  std::to_string(nVoteSignal) + "|" + std::to_string(nVoteOutcome) + "|" + std::to_string(nTime);
183 
184  if (!CMessageSigner::SignMessage(strMessage, vchSig, key)) {
185  LogPrintf("CGovernanceVote::Sign -- SignMessage() failed\n");
186  return false;
187  }
188 
189  if (!CMessageSigner::VerifyMessage(keyID, vchSig, strMessage, strError)) {
190  LogPrintf("CGovernanceVote::Sign -- VerifyMessage() failed, error: %s\n", strError);
191  return false;
192  }
193  }
194 
195  return true;
196 }
197 
198 bool CGovernanceVote::CheckSignature(const CKeyID& keyID) const
199 {
200  std::string strError;
201 
202  // Harden Spork6 so that it is active on testnet and no other networks
203  if (Params().NetworkIDString() == CBaseChainParams::TESTNET) {
205 
206  if (!CHashSigner::VerifyHash(hash, keyID, vchSig, strError)) {
207  LogPrint(BCLog::GOBJECT, "CGovernanceVote::IsValid -- VerifyHash() failed, error: %s\n", strError);
208  return false;
209  }
210  } else {
211  std::string strMessage = masternodeOutpoint.ToStringShort() + "|" + nParentHash.ToString() + "|" +
212  std::to_string(nVoteSignal) + "|" +
213  std::to_string(nVoteOutcome) + "|" +
214  std::to_string(nTime);
215 
216  if (!CMessageSigner::VerifyMessage(keyID, vchSig, strMessage, strError)) {
217  LogPrint(BCLog::GOBJECT, "CGovernanceVote::IsValid -- VerifyMessage() failed, error: %s\n", strError);
218  return false;
219  }
220  }
221 
222  return true;
223 }
224 
226 {
228  CBLSSignature sig = key.Sign(hash);
229  if (!sig.IsValid()) {
230  return false;
231  }
232  sig.GetBuf(vchSig);
233  return true;
234 }
235 
237 {
239  CBLSSignature sig;
240  sig.SetBuf(vchSig);
241  if (!sig.VerifyInsecure(pubKey, hash)) {
242  LogPrintf("CGovernanceVote::CheckSignature -- VerifyInsecure() failed\n");
243  return false;
244  }
245  return true;
246 }
247 
248 bool CGovernanceVote::IsValid(bool useVotingKey) const
249 {
250  if (nTime > GetAdjustedTime() + (60 * 60)) {
251  LogPrint(BCLog::GOBJECT, "CGovernanceVote::IsValid -- vote is too far ahead of current time - %s - nTime %lli - Max Time %lli\n", GetHash().ToString(), nTime, GetAdjustedTime() + (60 * 60));
252  return false;
253  }
254 
255  // support up to MAX_SUPPORTED_VOTE_SIGNAL, can be extended
257  LogPrint(BCLog::GOBJECT, "CGovernanceVote::IsValid -- Client attempted to vote on invalid signal(%d) - %s\n", nVoteSignal, GetHash().ToString());
258  return false;
259  }
260 
261  // 0=none, 1=yes, 2=no, 3=abstain. Beyond that reject votes
262  if (nVoteOutcome > 3) {
263  LogPrint(BCLog::GOBJECT, "CGovernanceVote::IsValid -- Client attempted to vote on invalid outcome(%d) - %s\n", nVoteSignal, GetHash().ToString());
264  return false;
265  }
266 
267  auto dmn = deterministicMNManager->GetListAtChainTip().GetMNByCollateral(masternodeOutpoint);
268  if (!dmn) {
269  LogPrint(BCLog::GOBJECT, "CGovernanceVote::IsValid -- Unknown Masternode - %s\n", masternodeOutpoint.ToStringShort());
270  return false;
271  }
272 
273  if (useVotingKey) {
274  return CheckSignature(dmn->pdmnState->keyIDVoting);
275  } else {
276  return CheckSignature(dmn->pdmnState->pubKeyOperator.Get());
277  }
278 }
279 
280 bool operator==(const CGovernanceVote& vote1, const CGovernanceVote& vote2)
281 {
282  bool fResult = ((vote1.masternodeOutpoint == vote2.masternodeOutpoint) &&
283  (vote1.nParentHash == vote2.nParentHash) &&
284  (vote1.nVoteOutcome == vote2.nVoteOutcome) &&
285  (vote1.nVoteSignal == vote2.nVoteSignal) &&
286  (vote1.nTime == vote2.nTime));
287  return fResult;
288 }
289 
290 bool operator<(const CGovernanceVote& vote1, const CGovernanceVote& vote2)
291 {
292  bool fResult = (vote1.masternodeOutpoint < vote2.masternodeOutpoint);
293  if (!fResult) {
294  return false;
295  }
296  fResult = (vote1.masternodeOutpoint == vote2.masternodeOutpoint);
297 
298  fResult = fResult && (vote1.nParentHash < vote2.nParentHash);
299  if (!fResult) {
300  return false;
301  }
302  fResult = fResult && (vote1.nParentHash == vote2.nParentHash);
303 
304  fResult = fResult && (vote1.nVoteOutcome < vote2.nVoteOutcome);
305  if (!fResult) {
306  return false;
307  }
308  fResult = fResult && (vote1.nVoteOutcome == vote2.nVoteOutcome);
309 
310  fResult = fResult && (vote1.nVoteSignal == vote2.nVoteSignal);
311  if (!fResult) {
312  return false;
313  }
314  fResult = fResult && (vote1.nVoteSignal == vote2.nVoteSignal);
315 
316  fResult = fResult && (vote1.nTime < vote2.nTime);
317 
318  return fResult;
319 }
static bool VerifyHash(const uint256 &hash, const CPubKey &pubkey, const std::vector< unsigned char > &vchSig, std::string &strErrorRet)
Verify the hash signature, returns true if succcessful.
CMasternodeSync masternodeSync
uint256 GetHash() const
GetHash()
bool operator<(const CGovernanceVote &vote1, const CGovernanceVote &vote2)
COutPoint masternodeOutpoint
void SetBuf(const void *buf, size_t size)
Definition: bls.h:99
inv message data
Definition: protocol.h:429
std::vector< unsigned char > vchSig
static const int MIN_GOVERNANCE_PEER_PROTO_VERSION
static bool SignHash(const uint256 &hash, const CKey &key, std::vector< unsigned char > &vchSigRet)
Sign the hash, returns true if successful.
vote_outcome_enum_t GetOutcome() const
bool VerifyInsecure(const CBLSPublicKey &pubKey, const uint256 &hash) const
Definition: bls.cpp:335
false true true true
Definition: bls_dkg.cpp:176
static vote_signal_enum_t ConvertVoteSignal(const std::string &strVoteSignal)
static std::string ConvertOutcomeToString(vote_outcome_enum_t nOutcome)
std::unique_ptr< CDeterministicMNManager > deterministicMNManager
const uint256 hash
Memory only.
static bool VerifyMessage(const CPubKey &pubkey, const std::vector< unsigned char > &vchSig, const std::string &strMessage, std::string &strErrorRet)
Verify the message signature, returns true if succcessful.
bool IsValid() const
static bool SignMessage(const std::string &strMessage, std::vector< unsigned char > &vchSigRet, const CKey &key)
Sign the message, returns true if successful.
void GetBuf(void *buf, size_t size) const
Definition: bls.h:122
uint256 SerializeHash(const T &obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
Compute the 256-bit hash of an object&#39;s serialization.
Definition: hash.h:254
false
Definition: bls_dkg.cpp:168
#define LogPrintf(...)
Definition: util.h:203
uint256 GetSignatureHash() const
static const int GOVERNANCE_POSE_BANNED_VOTES_VERSION
vote_signal_enum_t GetSignal() const
bool CheckSignature(const CKeyID &keyID) const
Definition: net.h:136
std::string ToString() const
Definition: uint256.cpp:62
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:26
bool operator==(const CGovernanceVote &vote1, const CGovernanceVote &vote2)
#define LogPrint(category,...)
Definition: util.h:214
uint256 GetHash()
Definition: hash.h:203
256-bit opaque blob.
Definition: uint256.h:123
const CChainParams & Params()
Return the currently selected parameters.
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:14
vote_outcome_enum_t
int64_t GetAdjustedTime()
Definition: timedata.cpp:35
void Relay(CConnman &connman) const
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:20
vote_signal_enum_t
void RelayInv(CInv &inv, const int minProtoVersion=MIN_PEER_PROTO_VERSION, bool fAllowMasternodeConnections=false)
Definition: net.cpp:3482
static const std::string TESTNET
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:184
An encapsulated private key.
Definition: key.h:27
bool Sign(const CKey &key, const CKeyID &keyID)
static std::string ConvertSignalToString(vote_signal_enum_t nSignal)
void UpdateHash() const
static const int MAX_SUPPORTED_VOTE_SIGNAL
bool IsValid() const
Definition: bls.h:94
static vote_outcome_enum_t ConvertVoteOutcome(const std::string &strVoteOutcome)
std::string ToString() const
CBLSSignature Sign(const uint256 &hash) const
Definition: bls.cpp:160
std::string ToStringShort() const
Definition: transaction.cpp:17
Released under the MIT license