Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

governance.cpp
Go to the documentation of this file.
1 // Copyright (c) 2014-2020 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 
6 #include <consensus/validation.h>
7 #include <core_io.h>
12 #include <init.h>
13 #include <txmempool.h>
14 #include <validation.h>
16 #include <messagesigner.h>
17 #include <rpc/server.h>
18 #include <util.h>
19 #include <utilmoneystr.h>
20 #include <wallet/rpcwallet.h>
21 #ifdef ENABLE_WALLET
22 #include <wallet/wallet.h>
23 #endif // ENABLE_WALLET
24 
26 {
27  throw std::runtime_error(
28  "gobject count (\"mode\")\n"
29  "Count governance objects and votes\n"
30  "\nArguments:\n"
31  "1. \"mode\" (string, optional, default: \"json\") Output format: json (\"json\") or string in free form (\"all\")\n"
32  );
33 }
34 
36 {
37  if (request.fHelp || request.params.size() > 2)
39 
40  std::string strMode{"json"};
41 
42  if (!request.params[1].isNull()) {
43  strMode = request.params[1].get_str();
44  }
45 
46  if (strMode != "json" && strMode != "all")
48 
49  return strMode == "json" ? governance.ToJson() : governance.ToString();
50 }
51 
53 {
54  throw std::runtime_error(
55  "gobject deserialize \"hex_data\"\n"
56  "Deserialize governance object from hex string to JSON\n"
57  "\nArguments:\n"
58  "1. \"hex_data\" (string, required) data in hex string form\n"
59  );
60 }
61 
63 {
64  if (request.fHelp || request.params.size() != 2)
66 
67  std::string strHex = request.params[1].get_str();
68 
69  std::vector<unsigned char> v = ParseHex(strHex);
70  std::string s(v.begin(), v.end());
71 
73  u.read(s);
74 
75  return u.write().c_str();
76 }
77 
79 {
80  throw std::runtime_error(
81  "gobject check \"hex_data\"\n"
82  "Validate governance object data (proposal only)\n"
83  "\nArguments:\n"
84  "1. \"hex_data\" (string, required) data in hex string form\n"
85  );
86 }
87 
89 {
90  if (request.fHelp || request.params.size() != 2)
92 
93  // ASSEMBLE NEW GOVERNANCE OBJECT FROM USER PARAMETERS
94 
95  uint256 hashParent;
96 
97  int nRevision = 1;
98 
99  int64_t nTime = GetAdjustedTime();
100  std::string strDataHex = request.params[1].get_str();
101 
102  CGovernanceObject govobj(hashParent, nRevision, nTime, uint256(), strDataHex);
103 
104  if (govobj.GetObjectType() == GOVERNANCE_OBJECT_PROPOSAL) {
105  CProposalValidator validator(strDataHex, false);
106  if (!validator.Validate()) {
107  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid proposal data, error messages:" + validator.GetErrorMessages());
108  }
109  } else {
110  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid object type, only proposals can be validated");
111  }
112 
113  UniValue objResult(UniValue::VOBJ);
114 
115  objResult.push_back(Pair("Object status", "OK"));
116 
117  return objResult;
118 }
119 
120 #ifdef ENABLE_WALLET
121 void gobject_prepare_help(CWallet* const pwallet)
122 {
123  throw std::runtime_error(
124  "gobject prepare <parent-hash> <revision> <time> <data-hex>\n"
125  "Prepare governance object by signing and creating tx\n"
126  + HelpRequiringPassphrase(pwallet) + "\n"
127  "\nArguments:\n"
128  "1. parent-hash (string, required) hash of the parent object, \"0\" is root\n"
129  "2. revision (numeric, required) object revision in the system\n"
130  "3. time (numeric, required) time this object was created\n"
131  "4. data-hex (string, required) data in hex string form\n"
132  "5. use-IS (boolean, optional, default=false) Deprecated and ignored\n"
133  "6. outputHash (string, optional) the single output to submit the proposal fee from\n"
134  "7. outputIndex (numeric, optional) The output index.\n"
135  );
136 }
137 
138 UniValue gobject_prepare(const JSONRPCRequest& request)
139 {
140  CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
141  if (request.fHelp || (request.params.size() != 5 && request.params.size() != 6 && request.params.size() != 8))
142  gobject_prepare_help(pwallet);
143 
144  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
145  return NullUniValue;
146 
147  EnsureWalletIsUnlocked(pwallet);
148 
149  // ASSEMBLE NEW GOVERNANCE OBJECT FROM USER PARAMETERS
150 
151  uint256 hashParent;
152 
153  // -- attach to root node (root node doesn't really exist, but has a hash of zero)
154  if (request.params[1].get_str() == "0") {
155  hashParent = uint256();
156  } else {
157  hashParent = ParseHashV(request.params[1], "fee-txid, parameter 1");
158  }
159 
160  std::string strRevision = request.params[2].get_str();
161  std::string strTime = request.params[3].get_str();
162  int nRevision = atoi(strRevision);
163  int64_t nTime = atoi64(strTime);
164  std::string strDataHex = request.params[4].get_str();
165 
166  // CREATE A NEW COLLATERAL TRANSACTION FOR THIS SPECIFIC OBJECT
167 
168  CGovernanceObject govobj(hashParent, nRevision, nTime, uint256(), strDataHex);
169 
170  // This command is dangerous because it consumes 5 DASH irreversibly.
171  // If params are lost, it's very hard to bruteforce them and yet
172  // users ignore all instructions on dashcentral etc. and do not save them...
173  // Let's log them here and hope users do not mess with debug.log
174  LogPrintf("gobject_prepare -- params: %s %s %s %s, data: %s, hash: %s\n",
175  request.params[1].get_str(), request.params[2].get_str(),
176  request.params[3].get_str(), request.params[4].get_str(),
177  govobj.GetDataAsPlainString(), govobj.GetHash().ToString());
178 
179  if (govobj.GetObjectType() == GOVERNANCE_OBJECT_PROPOSAL) {
180  CProposalValidator validator(strDataHex, false);
181  if (!validator.Validate()) {
182  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid proposal data, error messages:" + validator.GetErrorMessages());
183  }
184  }
185 
186  if (govobj.GetObjectType() == GOVERNANCE_OBJECT_TRIGGER) {
187  throw JSONRPCError(RPC_INVALID_PARAMETER, "Trigger objects need not be prepared (however only masternodes can create them)");
188  }
189 
191  LOCK(pwallet->cs_wallet);
192 
193  std::string strError = "";
194  if (!govobj.IsValidLocally(strError, false))
195  throw JSONRPCError(RPC_INTERNAL_ERROR, "Governance object is not valid - " + govobj.GetHash().ToString() + " - " + strError);
196 
197  // If specified, spend this outpoint as the proposal fee
198  COutPoint outpoint;
199  outpoint.SetNull();
200  if (!request.params[6].isNull() && !request.params[7].isNull()) {
201  uint256 collateralHash = ParseHashV(request.params[6], "outputHash");
202  int32_t collateralIndex = ParseInt32V(request.params[7], "outputIndex");
203  if (collateralHash.IsNull() || collateralIndex < 0) {
204  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("invalid hash or index: %s-%d", collateralHash.ToString(), collateralIndex));
205  }
206  outpoint = COutPoint(collateralHash, (uint32_t)collateralIndex);
207  }
208 
209  CWalletTx wtx;
210  if (!pwallet->GetBudgetSystemCollateralTX(wtx, govobj.GetHash(), govobj.GetMinCollateralFee(), outpoint)) {
211  std::string err = "Error making collateral transaction for governance object. Please check your wallet balance and make sure your wallet is unlocked.";
212  if (!request.params[6].isNull() && !request.params[7].isNull()) {
213  err += "Please verify your specified output is valid and is enough for the combined proposal fee and transaction fee.";
214  }
215  throw JSONRPCError(RPC_INTERNAL_ERROR, err);
216  }
217 
218  // -- make our change address
219  CReserveKey reservekey(pwallet);
220  // -- send the tx to the network
221  CValidationState state;
222  if (!pwallet->CommitTransaction(wtx, reservekey, g_connman.get(), state)) {
223  throw JSONRPCError(RPC_INTERNAL_ERROR, "CommitTransaction failed! Reason given: " + state.GetRejectReason());
224  }
225 
226  LogPrint(BCLog::GOBJECT, "gobject_prepare -- GetDataAsPlainString = %s, hash = %s, txid = %s\n",
227  govobj.GetDataAsPlainString(), govobj.GetHash().ToString(), wtx.GetHash().ToString());
228 
229  return wtx.GetHash().ToString();
230 }
231 #endif // ENABLE_WALLET
232 
234 {
235  throw std::runtime_error(
236  "gobject submit <parent-hash> <revision> <time> <data-hex> <fee-txid>\n"
237  "Submit governance object to network\n"
238  "\nArguments:\n"
239  "1. parent-hash (string, required) hash of the parent object, \"0\" is root\n"
240  "2. revision (numeric, required) object revision in the system\n"
241  "3. time (numeric, required) time this object was created\n"
242  "4. data-hex (string, required) data in hex string form\n"
243  "5. fee-txid (string, optional) fee-tx id, required for all objects except triggers"
244  );
245 }
246 
248 {
249  if (request.fHelp || ((request.params.size() < 5) || (request.params.size() > 6)))
251 
253  throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Must wait for client to sync with masternode network. Try again in a minute or so.");
254  }
255 
256  auto mnList = deterministicMNManager->GetListAtChainTip();
257  bool fMnFound = mnList.HasValidMNByCollateral(activeMasternodeInfo.outpoint);
258 
259  LogPrint(BCLog::GOBJECT, "gobject_submit -- pubKeyOperator = %s, outpoint = %s, params.size() = %lld, fMnFound = %d\n",
261  activeMasternodeInfo.outpoint.ToStringShort(), request.params.size(), fMnFound);
262 
263  // ASSEMBLE NEW GOVERNANCE OBJECT FROM USER PARAMETERS
264 
265  uint256 txidFee;
266 
267  if (!request.params[5].isNull()) {
268  txidFee = ParseHashV(request.params[5], "fee-txid, parameter 6");
269  }
270  uint256 hashParent;
271  if (request.params[1].get_str() == "0") { // attach to root node (root node doesn't really exist, but has a hash of zero)
272  hashParent = uint256();
273  } else {
274  hashParent = ParseHashV(request.params[1], "parent object hash, parameter 2");
275  }
276 
277  // GET THE PARAMETERS FROM USER
278 
279  std::string strRevision = request.params[2].get_str();
280  std::string strTime = request.params[3].get_str();
281  int nRevision = atoi(strRevision);
282  int64_t nTime = atoi64(strTime);
283  std::string strDataHex = request.params[4].get_str();
284 
285  CGovernanceObject govobj(hashParent, nRevision, nTime, txidFee, strDataHex);
286 
287  LogPrint(BCLog::GOBJECT, "gobject_submit -- GetDataAsPlainString = %s, hash = %s, txid = %s\n",
288  govobj.GetDataAsPlainString(), govobj.GetHash().ToString(), txidFee.ToString());
289 
290  if (govobj.GetObjectType() == GOVERNANCE_OBJECT_PROPOSAL) {
291  CProposalValidator validator(strDataHex, false);
292  if (!validator.Validate()) {
293  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid proposal data, error messages:" + validator.GetErrorMessages());
294  }
295  }
296 
297  // Attempt to sign triggers if we are a MN
298  if (govobj.GetObjectType() == GOVERNANCE_OBJECT_TRIGGER) {
299  if (fMnFound) {
302  } else {
303  LogPrintf("gobject(submit) -- Object submission rejected because node is not a masternode\n");
304  throw JSONRPCError(RPC_INVALID_PARAMETER, "Only valid masternodes can submit this type of object");
305  }
306  } else if (request.params.size() != 6) {
307  LogPrintf("gobject(submit) -- Object submission rejected because fee tx not provided\n");
308  throw JSONRPCError(RPC_INVALID_PARAMETER, "The fee-txid parameter must be included to submit this type of object");
309  }
310 
311  std::string strHash = govobj.GetHash().ToString();
312 
313  std::string strError = "";
314  bool fMissingConfirmations;
315  {
316  LOCK(cs_main);
317  if (!govobj.IsValidLocally(strError, fMissingConfirmations, true) && !fMissingConfirmations) {
318  LogPrintf("gobject(submit) -- Object submission rejected because object is not valid - hash = %s, strError = %s\n", strHash, strError);
319  throw JSONRPCError(RPC_INTERNAL_ERROR, "Governance object is not valid - " + strHash + " - " + strError);
320  }
321  }
322 
323  // RELAY THIS OBJECT
324  // Reject if rate check fails but don't update buffer
325  if (!governance.MasternodeRateCheck(govobj)) {
326  LogPrintf("gobject(submit) -- Object submission rejected because of rate check failure - hash = %s\n", strHash);
327  throw JSONRPCError(RPC_INVALID_PARAMETER, "Object creation rate limit exceeded");
328  }
329 
330  LogPrintf("gobject(submit) -- Adding locally created governance object - %s\n", strHash);
331 
332  if (fMissingConfirmations) {
334  govobj.Relay(*g_connman);
335  } else {
337  }
338 
339  return govobj.GetHash().ToString();
340 }
341 
343 {
344  throw std::runtime_error(
345  "gobject vote-conf <governance-hash> <vote> <vote-outcome>\n"
346  "Vote on a governance object by masternode configured in dash.conf\n"
347  "\nArguments:\n"
348  "1. governance-hash (string, required) hash of the governance object\n"
349  "2. vote (string, required) vote, possible values: [funding|valid|delete|endorsed]\n"
350  "3. vote-outcome (string, required) vote outcome, possible values: [yes|no|abstain]\n"
351  );
352 }
353 
355 {
356  if (request.fHelp || request.params.size() != 4)
358 
359  uint256 hash;
360 
361  hash = ParseHashV(request.params[1], "Object hash");
362  std::string strVoteSignal = request.params[2].get_str();
363  std::string strVoteOutcome = request.params[3].get_str();
364 
365  vote_signal_enum_t eVoteSignal = CGovernanceVoting::ConvertVoteSignal(strVoteSignal);
366  if (eVoteSignal == VOTE_SIGNAL_NONE) {
368  "Invalid vote signal. Please using one of the following: "
369  "(funding|valid|delete|endorsed)");
370  }
371 
372  vote_outcome_enum_t eVoteOutcome = CGovernanceVoting::ConvertVoteOutcome(strVoteOutcome);
373  if (eVoteOutcome == VOTE_OUTCOME_NONE) {
374  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid vote outcome. Please use one of the following: 'yes', 'no' or 'abstain'");
375  }
376 
377  int govObjType;
378  {
379  LOCK(governance.cs);
381  if (!pGovObj) {
382  throw JSONRPCError(RPC_INVALID_PARAMETER, "Governance object not found");
383  }
384  govObjType = pGovObj->GetObjectType();
385  }
386 
387  int nSuccessful = 0;
388  int nFailed = 0;
389 
390  UniValue resultsObj(UniValue::VOBJ);
391 
392  UniValue statusObj(UniValue::VOBJ);
393  UniValue returnObj(UniValue::VOBJ);
394 
395  auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMNByCollateral(activeMasternodeInfo.outpoint);
396 
397  if (!dmn) {
398  nFailed++;
399  statusObj.push_back(Pair("result", "failed"));
400  statusObj.push_back(Pair("errorMessage", "Can't find masternode by collateral output"));
401  resultsObj.push_back(Pair("dash.conf", statusObj));
402  returnObj.push_back(Pair("overall", strprintf("Voted successfully %d time(s) and failed %d time(s).", nSuccessful, nFailed)));
403  returnObj.push_back(Pair("detail", resultsObj));
404  return returnObj;
405  }
406 
407  CGovernanceVote vote(dmn->collateralOutpoint, hash, eVoteSignal, eVoteOutcome);
408 
409  bool signSuccess = false;
410  if (govObjType == GOVERNANCE_OBJECT_PROPOSAL && eVoteSignal == VOTE_SIGNAL_FUNDING) {
411  throw JSONRPCError(RPC_INVALID_PARAMETER, "Can't use vote-conf for proposals");
412  }
414  signSuccess = vote.Sign(*activeMasternodeInfo.blsKeyOperator);
415  }
416 
417  if (!signSuccess) {
418  nFailed++;
419  statusObj.push_back(Pair("result", "failed"));
420  statusObj.push_back(Pair("errorMessage", "Failure to sign."));
421  resultsObj.push_back(Pair("dash.conf", statusObj));
422  returnObj.push_back(Pair("overall", strprintf("Voted successfully %d time(s) and failed %d time(s).", nSuccessful, nFailed)));
423  returnObj.push_back(Pair("detail", resultsObj));
424  return returnObj;
425  }
426 
427  CGovernanceException exception;
428  if (governance.ProcessVoteAndRelay(vote, exception, *g_connman)) {
429  nSuccessful++;
430  statusObj.push_back(Pair("result", "success"));
431  } else {
432  nFailed++;
433  statusObj.push_back(Pair("result", "failed"));
434  statusObj.push_back(Pair("errorMessage", exception.GetMessage()));
435  }
436 
437  resultsObj.push_back(Pair("dash.conf", statusObj));
438 
439  returnObj.push_back(Pair("overall", strprintf("Voted successfully %d time(s) and failed %d time(s).", nSuccessful, nFailed)));
440  returnObj.push_back(Pair("detail", resultsObj));
441 
442  return returnObj;
443 }
444 
445 UniValue VoteWithMasternodes(const std::map<uint256, CKey>& keys,
446  const uint256& hash, vote_signal_enum_t eVoteSignal,
447  vote_outcome_enum_t eVoteOutcome)
448 {
449  int govObjType;
450  {
451  LOCK(governance.cs);
453  if (!pGovObj) {
454  throw JSONRPCError(RPC_INVALID_PARAMETER, "Governance object not found");
455  }
456  govObjType = pGovObj->GetObjectType();
457  }
458 
459  int nSuccessful = 0;
460  int nFailed = 0;
461 
462  auto mnList = deterministicMNManager->GetListAtChainTip();
463 
464  UniValue resultsObj(UniValue::VOBJ);
465 
466  for (const auto& p : keys) {
467  const auto& proTxHash = p.first;
468  const auto& key = p.second;
469 
470  UniValue statusObj(UniValue::VOBJ);
471 
472  auto dmn = mnList.GetValidMN(proTxHash);
473  if (!dmn) {
474  nFailed++;
475  statusObj.push_back(Pair("result", "failed"));
476  statusObj.push_back(Pair("errorMessage", "Can't find masternode by proTxHash"));
477  resultsObj.push_back(Pair(proTxHash.ToString(), statusObj));
478  continue;
479  }
480 
481  CGovernanceVote vote(dmn->collateralOutpoint, hash, eVoteSignal, eVoteOutcome);
482  if (!vote.Sign(key, key.GetPubKey().GetID())) {
483  nFailed++;
484  statusObj.push_back(Pair("result", "failed"));
485  statusObj.push_back(Pair("errorMessage", "Failure to sign."));
486  resultsObj.push_back(Pair(proTxHash.ToString(), statusObj));
487  continue;
488  }
489 
490  CGovernanceException exception;
491  if (governance.ProcessVoteAndRelay(vote, exception, *g_connman)) {
492  nSuccessful++;
493  statusObj.push_back(Pair("result", "success"));
494  } else {
495  nFailed++;
496  statusObj.push_back(Pair("result", "failed"));
497  statusObj.push_back(Pair("errorMessage", exception.GetMessage()));
498  }
499 
500  resultsObj.push_back(Pair(proTxHash.ToString(), statusObj));
501  }
502 
503  UniValue returnObj(UniValue::VOBJ);
504  returnObj.push_back(Pair("overall", strprintf("Voted successfully %d time(s) and failed %d time(s).", nSuccessful, nFailed)));
505  returnObj.push_back(Pair("detail", resultsObj));
506 
507  return returnObj;
508 }
509 
510 #ifdef ENABLE_WALLET
511 void gobject_vote_many_help(CWallet* const pwallet)
512 {
513  throw std::runtime_error(
514  "gobject vote-many <governance-hash> <vote> <vote-outcome>\n"
515  "Vote on a governance object by all masternodes for which the voting key is present in the local wallet\n"
516  + HelpRequiringPassphrase(pwallet) + "\n"
517  "\nArguments:\n"
518  "1. governance-hash (string, required) hash of the governance object\n"
519  "2. vote (string, required) vote, possible values: [funding|valid|delete|endorsed]\n"
520  "3. vote-outcome (string, required) vote outcome, possible values: [yes|no|abstain]\n"
521  );
522 }
523 
524 UniValue gobject_vote_many(const JSONRPCRequest& request)
525 {
526  CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
527  if (request.fHelp || request.params.size() != 4)
528  gobject_vote_many_help(pwallet);
529 
530  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
531  return NullUniValue;
532 
533  uint256 hash = ParseHashV(request.params[1], "Object hash");
534  std::string strVoteSignal = request.params[2].get_str();
535  std::string strVoteOutcome = request.params[3].get_str();
536 
537  vote_signal_enum_t eVoteSignal = CGovernanceVoting::ConvertVoteSignal(strVoteSignal);
538  if (eVoteSignal == VOTE_SIGNAL_NONE) {
540  "Invalid vote signal. Please using one of the following: "
541  "(funding|valid|delete|endorsed)");
542  }
543 
544  vote_outcome_enum_t eVoteOutcome = CGovernanceVoting::ConvertVoteOutcome(strVoteOutcome);
545  if (eVoteOutcome == VOTE_OUTCOME_NONE) {
546  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid vote outcome. Please use one of the following: 'yes', 'no' or 'abstain'");
547  }
548 
549  EnsureWalletIsUnlocked(pwallet);
550 
551  std::map<uint256, CKey> votingKeys;
552 
553  auto mnList = deterministicMNManager->GetListAtChainTip();
554  mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) {
555  CKey votingKey;
556  if (pwallet->GetKey(dmn->pdmnState->keyIDVoting, votingKey)) {
557  votingKeys.emplace(dmn->proTxHash, votingKey);
558  }
559  });
560 
561  return VoteWithMasternodes(votingKeys, hash, eVoteSignal, eVoteOutcome);
562 }
563 
564 void gobject_vote_alias_help(CWallet* const pwallet)
565 {
566  throw std::runtime_error(
567  "gobject vote-alias <governance-hash> <vote> <vote-outcome> <protx-hash>\n"
568  "Vote on a governance object by masternode's voting key (if present in local wallet)\n"
569  + HelpRequiringPassphrase(pwallet) + "\n"
570  "\nArguments:\n"
571  "1. governance-hash (string, required) hash of the governance object\n"
572  "2. vote (string, required) vote, possible values: [funding|valid|delete|endorsed]\n"
573  "3. vote-outcome (string, required) vote outcome, possible values: [yes|no|abstain]\n"
574  "4. protx-hash (string, required) masternode's proTxHash"
575  );
576 }
577 
578 UniValue gobject_vote_alias(const JSONRPCRequest& request)
579 {
580  CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
581  if (request.fHelp || request.params.size() != 5)
582  gobject_vote_alias_help(pwallet);
583 
584  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
585  return NullUniValue;
586 
587  uint256 hash = ParseHashV(request.params[1], "Object hash");
588  std::string strVoteSignal = request.params[2].get_str();
589  std::string strVoteOutcome = request.params[3].get_str();
590 
591  vote_signal_enum_t eVoteSignal = CGovernanceVoting::ConvertVoteSignal(strVoteSignal);
592  if (eVoteSignal == VOTE_SIGNAL_NONE) {
594  "Invalid vote signal. Please using one of the following: "
595  "(funding|valid|delete|endorsed)");
596  }
597 
598  vote_outcome_enum_t eVoteOutcome = CGovernanceVoting::ConvertVoteOutcome(strVoteOutcome);
599  if (eVoteOutcome == VOTE_OUTCOME_NONE) {
600  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid vote outcome. Please use one of the following: 'yes', 'no' or 'abstain'");
601  }
602 
603  EnsureWalletIsUnlocked(pwallet);
604 
605  uint256 proTxHash = ParseHashV(request.params[4], "protx-hash");
606  auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMN(proTxHash);
607  if (!dmn) {
608  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid or unknown proTxHash");
609  }
610 
611  CKey votingKey;
612  if (!pwallet->GetKey(dmn->pdmnState->keyIDVoting, votingKey)) {
613  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Private key for voting address %s not known by wallet", EncodeDestination(dmn->pdmnState->keyIDVoting)));
614  }
615 
616  std::map<uint256, CKey> votingKeys;
617  votingKeys.emplace(proTxHash, votingKey);
618 
619  return VoteWithMasternodes(votingKeys, hash, eVoteSignal, eVoteOutcome);
620 }
621 #endif
622 
623 UniValue ListObjects(const std::string& strCachedSignal, const std::string& strType, int nStartTime)
624 {
625  UniValue objResult(UniValue::VOBJ);
626 
627  // GET MATCHING GOVERNANCE OBJECTS
628 
630 
631  std::vector<const CGovernanceObject*> objs = governance.GetAllNewerThan(nStartTime);
633 
634  // CREATE RESULTS FOR USER
635 
636  for (const auto& pGovObj : objs) {
637  if (strCachedSignal == "valid" && !pGovObj->IsSetCachedValid()) continue;
638  if (strCachedSignal == "funding" && !pGovObj->IsSetCachedFunding()) continue;
639  if (strCachedSignal == "delete" && !pGovObj->IsSetCachedDelete()) continue;
640  if (strCachedSignal == "endorsed" && !pGovObj->IsSetCachedEndorsed()) continue;
641 
642  if (strType == "proposals" && pGovObj->GetObjectType() != GOVERNANCE_OBJECT_PROPOSAL) continue;
643  if (strType == "triggers" && pGovObj->GetObjectType() != GOVERNANCE_OBJECT_TRIGGER) continue;
644 
645  UniValue bObj(UniValue::VOBJ);
646  bObj.push_back(Pair("DataHex", pGovObj->GetDataAsHexString()));
647  bObj.push_back(Pair("DataString", pGovObj->GetDataAsPlainString()));
648  bObj.push_back(Pair("Hash", pGovObj->GetHash().ToString()));
649  bObj.push_back(Pair("CollateralHash", pGovObj->GetCollateralHash().ToString()));
650  bObj.push_back(Pair("ObjectType", pGovObj->GetObjectType()));
651  bObj.push_back(Pair("CreationTime", pGovObj->GetCreationTime()));
652  const COutPoint& masternodeOutpoint = pGovObj->GetMasternodeOutpoint();
653  if (masternodeOutpoint != COutPoint()) {
654  bObj.push_back(Pair("SigningMasternode", masternodeOutpoint.ToStringShort()));
655  }
656 
657  // REPORT STATUS FOR FUNDING VOTES SPECIFICALLY
658  bObj.push_back(Pair("AbsoluteYesCount", pGovObj->GetAbsoluteYesCount(VOTE_SIGNAL_FUNDING)));
659  bObj.push_back(Pair("YesCount", pGovObj->GetYesCount(VOTE_SIGNAL_FUNDING)));
660  bObj.push_back(Pair("NoCount", pGovObj->GetNoCount(VOTE_SIGNAL_FUNDING)));
661  bObj.push_back(Pair("AbstainCount", pGovObj->GetAbstainCount(VOTE_SIGNAL_FUNDING)));
662 
663  // REPORT VALIDITY AND CACHING FLAGS FOR VARIOUS SETTINGS
664  std::string strError = "";
665  bObj.push_back(Pair("fBlockchainValidity", pGovObj->IsValidLocally(strError, false)));
666  bObj.push_back(Pair("IsValidReason", strError.c_str()));
667  bObj.push_back(Pair("fCachedValid", pGovObj->IsSetCachedValid()));
668  bObj.push_back(Pair("fCachedFunding", pGovObj->IsSetCachedFunding()));
669  bObj.push_back(Pair("fCachedDelete", pGovObj->IsSetCachedDelete()));
670  bObj.push_back(Pair("fCachedEndorsed", pGovObj->IsSetCachedEndorsed()));
671 
672  objResult.push_back(Pair(pGovObj->GetHash().ToString(), bObj));
673  }
674 
675  return objResult;
676 }
677 
679 {
680  throw std::runtime_error(
681  "gobject list ( <signal> <type> )\n"
682  "List governance objects (can be filtered by signal and/or object type)\n"
683  "\nArguments:\n"
684  "1. signal (string, optional, default=valid) cached signal, possible values: [valid|funding|delete|endorsed|all]\n"
685  "2. type (string, optional, default=all) object type, possible values: [proposals|triggers|all]\n"
686  );
687 }
688 
690 {
691  if (request.fHelp || request.params.size() > 3)
693 
694  std::string strCachedSignal = "valid";
695  if (!request.params[1].isNull()) {
696  strCachedSignal = request.params[1].get_str();
697  }
698  if (strCachedSignal != "valid" && strCachedSignal != "funding" && strCachedSignal != "delete" && strCachedSignal != "endorsed" && strCachedSignal != "all")
699  return "Invalid signal, should be 'valid', 'funding', 'delete', 'endorsed' or 'all'";
700 
701  std::string strType = "all";
702  if (!request.params[2].isNull()) {
703  strType = request.params[2].get_str();
704  }
705  if (strType != "proposals" && strType != "triggers" && strType != "all")
706  return "Invalid type, should be 'proposals', 'triggers' or 'all'";
707 
708  return ListObjects(strCachedSignal, strType, 0);
709 }
710 
712 {
713  throw std::runtime_error(
714  "gobject diff ( <signal> <type> )\n"
715  "List differences since last diff or list\n"
716  "\nArguments:\n"
717  "1. signal (string, optional, default=valid) cached signal, possible values: [valid|funding|delete|endorsed|all]\n"
718  "2. type (string, optional, default=all) object type, possible values: [proposals|triggers|all]\n"
719  );
720 }
721 
723 {
724  if (request.fHelp || request.params.size() > 3)
726 
727  std::string strCachedSignal = "valid";
728  if (!request.params[1].isNull()) {
729  strCachedSignal = request.params[1].get_str();
730  }
731  if (strCachedSignal != "valid" && strCachedSignal != "funding" && strCachedSignal != "delete" && strCachedSignal != "endorsed" && strCachedSignal != "all")
732  return "Invalid signal, should be 'valid', 'funding', 'delete', 'endorsed' or 'all'";
733 
734  std::string strType = "all";
735  if (!request.params[2].isNull()) {
736  strType = request.params[2].get_str();
737  }
738  if (strType != "proposals" && strType != "triggers" && strType != "all")
739  return "Invalid type, should be 'proposals', 'triggers' or 'all'";
740 
741  return ListObjects(strCachedSignal, strType, governance.GetLastDiffTime());
742 }
743 
745 {
746  throw std::runtime_error(
747  "gobject get <governance-hash>\n"
748  "Get governance object by hash\n"
749  "\nArguments:\n"
750  "1. governance-hash (string, required) object id\n"
751  );
752 }
753 
755 {
756  if (request.fHelp || request.params.size() != 2)
758 
759  // COLLECT VARIABLES FROM OUR USER
760  uint256 hash = ParseHashV(request.params[1], "GovObj hash");
761 
763 
764  // FIND THE GOVERNANCE OBJECT THE USER IS LOOKING FOR
766 
767  if (pGovObj == nullptr) {
768  throw JSONRPCError(RPC_INVALID_PARAMETER, "Unknown governance object");
769  }
770 
771  // REPORT BASIC OBJECT STATS
772 
773  UniValue objResult(UniValue::VOBJ);
774  objResult.push_back(Pair("DataHex", pGovObj->GetDataAsHexString()));
775  objResult.push_back(Pair("DataString", pGovObj->GetDataAsPlainString()));
776  objResult.push_back(Pair("Hash", pGovObj->GetHash().ToString()));
777  objResult.push_back(Pair("CollateralHash", pGovObj->GetCollateralHash().ToString()));
778  objResult.push_back(Pair("ObjectType", pGovObj->GetObjectType()));
779  objResult.push_back(Pair("CreationTime", pGovObj->GetCreationTime()));
780  const COutPoint& masternodeOutpoint = pGovObj->GetMasternodeOutpoint();
781  if (masternodeOutpoint != COutPoint()) {
782  objResult.push_back(Pair("SigningMasternode", masternodeOutpoint.ToStringShort()));
783  }
784 
785  // SHOW (MUCH MORE) INFORMATION ABOUT VOTES FOR GOVERNANCE OBJECT (THAN LIST/DIFF ABOVE)
786  // -- FUNDING VOTING RESULTS
787 
788  UniValue objFundingResult(UniValue::VOBJ);
789  objFundingResult.push_back(Pair("AbsoluteYesCount", pGovObj->GetAbsoluteYesCount(VOTE_SIGNAL_FUNDING)));
790  objFundingResult.push_back(Pair("YesCount", pGovObj->GetYesCount(VOTE_SIGNAL_FUNDING)));
791  objFundingResult.push_back(Pair("NoCount", pGovObj->GetNoCount(VOTE_SIGNAL_FUNDING)));
792  objFundingResult.push_back(Pair("AbstainCount", pGovObj->GetAbstainCount(VOTE_SIGNAL_FUNDING)));
793  objResult.push_back(Pair("FundingResult", objFundingResult));
794 
795  // -- VALIDITY VOTING RESULTS
796  UniValue objValid(UniValue::VOBJ);
797  objValid.push_back(Pair("AbsoluteYesCount", pGovObj->GetAbsoluteYesCount(VOTE_SIGNAL_VALID)));
798  objValid.push_back(Pair("YesCount", pGovObj->GetYesCount(VOTE_SIGNAL_VALID)));
799  objValid.push_back(Pair("NoCount", pGovObj->GetNoCount(VOTE_SIGNAL_VALID)));
800  objValid.push_back(Pair("AbstainCount", pGovObj->GetAbstainCount(VOTE_SIGNAL_VALID)));
801  objResult.push_back(Pair("ValidResult", objValid));
802 
803  // -- DELETION CRITERION VOTING RESULTS
804  UniValue objDelete(UniValue::VOBJ);
805  objDelete.push_back(Pair("AbsoluteYesCount", pGovObj->GetAbsoluteYesCount(VOTE_SIGNAL_DELETE)));
806  objDelete.push_back(Pair("YesCount", pGovObj->GetYesCount(VOTE_SIGNAL_DELETE)));
807  objDelete.push_back(Pair("NoCount", pGovObj->GetNoCount(VOTE_SIGNAL_DELETE)));
808  objDelete.push_back(Pair("AbstainCount", pGovObj->GetAbstainCount(VOTE_SIGNAL_DELETE)));
809  objResult.push_back(Pair("DeleteResult", objDelete));
810 
811  // -- ENDORSED VIA MASTERNODE-ELECTED BOARD
812  UniValue objEndorsed(UniValue::VOBJ);
813  objEndorsed.push_back(Pair("AbsoluteYesCount", pGovObj->GetAbsoluteYesCount(VOTE_SIGNAL_ENDORSED)));
814  objEndorsed.push_back(Pair("YesCount", pGovObj->GetYesCount(VOTE_SIGNAL_ENDORSED)));
815  objEndorsed.push_back(Pair("NoCount", pGovObj->GetNoCount(VOTE_SIGNAL_ENDORSED)));
816  objEndorsed.push_back(Pair("AbstainCount", pGovObj->GetAbstainCount(VOTE_SIGNAL_ENDORSED)));
817  objResult.push_back(Pair("EndorsedResult", objEndorsed));
818 
819  // --
820  std::string strError = "";
821  objResult.push_back(Pair("fLocalValidity", pGovObj->IsValidLocally(strError, false)));
822  objResult.push_back(Pair("IsValidReason", strError.c_str()));
823  objResult.push_back(Pair("fCachedValid", pGovObj->IsSetCachedValid()));
824  objResult.push_back(Pair("fCachedFunding", pGovObj->IsSetCachedFunding()));
825  objResult.push_back(Pair("fCachedDelete", pGovObj->IsSetCachedDelete()));
826  objResult.push_back(Pair("fCachedEndorsed", pGovObj->IsSetCachedEndorsed()));
827  return objResult;
828 }
829 
831 {
832  throw std::runtime_error(
833  "gobject getcurrentvotes <governance-hash> (<txid> <vout>)\n"
834  "Get only current (tallying) votes for a governance object hash (does not include old votes)\n"
835  "\nArguments:\n"
836  "1. governance-hash (string, required) object id\n"
837  "2. txid (string, optional) masternode collateral txid\n"
838  "3. vout (string, optional) masternode collateral output index, required if <txid> presents\n"
839  );
840 }
841 
843 {
844  if (request.fHelp || (request.params.size() != 2 && request.params.size() != 4))
846 
847  // COLLECT PARAMETERS FROM USER
848 
849  uint256 hash = ParseHashV(request.params[1], "Governance hash");
850 
851  COutPoint mnCollateralOutpoint;
852  if (!request.params[2].isNull() && !request.params[3].isNull()) {
853  uint256 txid = ParseHashV(request.params[2], "Masternode Collateral hash");
854  std::string strVout = request.params[3].get_str();
855  mnCollateralOutpoint = COutPoint(txid, (uint32_t)atoi(strVout));
856  }
857 
858  // FIND OBJECT USER IS LOOKING FOR
859 
860  LOCK(governance.cs);
861 
863 
864  if (pGovObj == nullptr) {
865  throw JSONRPCError(RPC_INVALID_PARAMETER, "Unknown governance-hash");
866  }
867 
868  // REPORT RESULTS TO USER
869 
870  UniValue bResult(UniValue::VOBJ);
871 
872  // GET MATCHING VOTES BY HASH, THEN SHOW USERS VOTE INFORMATION
873 
874  std::vector<CGovernanceVote> vecVotes = governance.GetCurrentVotes(hash, mnCollateralOutpoint);
875  for (const auto& vote : vecVotes) {
876  bResult.push_back(Pair(vote.GetHash().ToString(), vote.ToString()));
877  }
878 
879  return bResult;
880 }
881 
882 [[ noreturn ]] void gobject_help()
883 {
884  throw std::runtime_error(
885  "gobject \"command\" ...\n"
886  "Set of commands to manage governance objects.\n"
887  "\nAvailable commands:\n"
888  " check - Validate governance object data (proposal only)\n"
889 #ifdef ENABLE_WALLET
890  " prepare - Prepare governance object by signing and creating tx\n"
891 #endif // ENABLE_WALLET
892  " submit - Submit governance object to network\n"
893  " deserialize - Deserialize governance object from hex string to JSON\n"
894  " count - Count governance objects and votes (additional param: 'json' or 'all', default: 'json')\n"
895  " get - Get governance object by hash\n"
896  " getcurrentvotes - Get only current (tallying) votes for a governance object hash (does not include old votes)\n"
897  " list - List governance objects (can be filtered by signal and/or object type)\n"
898  " diff - List differences since last diff\n"
899 #ifdef ENABLE_WALLET
900  " vote-alias - Vote on a governance object by masternode proTxHash\n"
901 #endif // ENABLE_WALLET
902  " vote-conf - Vote on a governance object by masternode configured in dash.conf\n"
903 #ifdef ENABLE_WALLET
904  " vote-many - Vote on a governance object by all masternodes for which the voting key is in the wallet\n"
905 #endif // ENABLE_WALLET
906  );
907 }
908 
910 {
911  std::string strCommand;
912  if (!request.params[0].isNull())
913  strCommand = request.params[0].get_str();
914 
915  if (request.fHelp && strCommand.empty()) {
916  gobject_help();
917  }
918 
919  if (strCommand == "count") {
920  return gobject_count(request);
921  } else if (strCommand == "deserialize") {
922  // DEBUG : TEST DESERIALIZATION OF GOVERNANCE META DATA
923  return gobject_deserialize(request);
924  } else if (strCommand == "check") {
925  // VALIDATE A GOVERNANCE OBJECT PRIOR TO SUBMISSION
926  return gobject_check(request);
927 #ifdef ENABLE_WALLET
928  } else if (strCommand == "prepare") {
929  // PREPARE THE GOVERNANCE OBJECT BY CREATING A COLLATERAL TRANSACTION
930  return gobject_prepare(request);
931 #endif // ENABLE_WALLET
932  } else if (strCommand == "submit") {
933  // AFTER COLLATERAL TRANSACTION HAS MATURED USER CAN SUBMIT GOVERNANCE OBJECT TO PROPAGATE NETWORK
934  /*
935  ------ Example Governance Item ------
936 
937  gobject submit 6e622bb41bad1fb18e7f23ae96770aeb33129e18bd9efe790522488e580a0a03 0 1 1464292854 "beer-reimbursement" 5b5b22636f6e7472616374222c207b2270726f6a6563745f6e616d65223a20225c22626565722d7265696d62757273656d656e745c22222c20227061796d656e745f61646472657373223a20225c225879324c4b4a4a64655178657948726e34744744514238626a6876464564615576375c22222c2022656e645f64617465223a202231343936333030343030222c20226465736372697074696f6e5f75726c223a20225c227777772e646173687768616c652e6f72672f702f626565722d7265696d62757273656d656e745c22222c2022636f6e74726163745f75726c223a20225c22626565722d7265696d62757273656d656e742e636f6d2f3030312e7064665c22222c20227061796d656e745f616d6f756e74223a20223233342e323334323232222c2022676f7665726e616e63655f6f626a6563745f6964223a2037342c202273746172745f64617465223a202231343833323534303030227d5d5d1
938  */
939  return gobject_submit(request);
940  } else if (strCommand == "vote-conf") {
941  return gobject_vote_conf(request);
942 #ifdef ENABLE_WALLET
943  } else if (strCommand == "vote-many") {
944  return gobject_vote_many(request);
945  } else if (strCommand == "vote-alias") {
946  return gobject_vote_alias(request);
947 #endif
948  } else if (strCommand == "list") {
949  // USERS CAN QUERY THE SYSTEM FOR A LIST OF VARIOUS GOVERNANCE ITEMS
950  return gobject_list(request);
951  } else if (strCommand == "diff") {
952  return gobject_diff(request);
953  } else if (strCommand == "get") {
954  // GET SPECIFIC GOVERNANCE ENTRY
955  return gobject_get(request);
956  } else if (strCommand == "getcurrentvotes") {
957  // GET VOTES FOR SPECIFIC GOVERNANCE OBJECT
958  return gobject_getcurrentvotes(request);
959  } else {
960  gobject_help();
961  }
962 }
963 
965 {
966  if (request.fHelp || request.params.size() != 7)
967  throw std::runtime_error(
968  "voteraw <mn-collateral-tx-hash> <mn-collateral-tx-index> <governance-hash> <vote-signal> [yes|no|abstain] <time> <vote-sig>\n"
969  "Compile and relay a governance vote with provided external signature instead of signing vote internally\n"
970  );
971 
972  uint256 hashMnCollateralTx = ParseHashV(request.params[0], "mn collateral tx hash");
973  int nMnCollateralTxIndex = request.params[1].get_int();
974  COutPoint outpoint = COutPoint(hashMnCollateralTx, nMnCollateralTxIndex);
975 
976  uint256 hashGovObj = ParseHashV(request.params[2], "Governance hash");
977  std::string strVoteSignal = request.params[3].get_str();
978  std::string strVoteOutcome = request.params[4].get_str();
979 
980  vote_signal_enum_t eVoteSignal = CGovernanceVoting::ConvertVoteSignal(strVoteSignal);
981  if (eVoteSignal == VOTE_SIGNAL_NONE) {
983  "Invalid vote signal. Please using one of the following: "
984  "(funding|valid|delete|endorsed)");
985  }
986 
987  vote_outcome_enum_t eVoteOutcome = CGovernanceVoting::ConvertVoteOutcome(strVoteOutcome);
988  if (eVoteOutcome == VOTE_OUTCOME_NONE) {
989  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid vote outcome. Please use one of the following: 'yes', 'no' or 'abstain'");
990  }
991 
992  int govObjType;
993  {
994  LOCK(governance.cs);
995  CGovernanceObject *pGovObj = governance.FindGovernanceObject(hashGovObj);
996  if (!pGovObj) {
997  throw JSONRPCError(RPC_INVALID_PARAMETER, "Governance object not found");
998  }
999  govObjType = pGovObj->GetObjectType();
1000  }
1001 
1002  int64_t nTime = request.params[5].get_int64();
1003  std::string strSig = request.params[6].get_str();
1004  bool fInvalid = false;
1005  std::vector<unsigned char> vchSig = DecodeBase64(strSig.c_str(), &fInvalid);
1006 
1007  if (fInvalid) {
1008  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
1009  }
1010 
1011  auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMNByCollateral(outpoint);
1012 
1013  if (!dmn) {
1014  throw JSONRPCError(RPC_INTERNAL_ERROR, "Failure to find masternode in list : " + outpoint.ToStringShort());
1015  }
1016 
1017  CGovernanceVote vote(outpoint, hashGovObj, eVoteSignal, eVoteOutcome);
1018  vote.SetTime(nTime);
1019  vote.SetSignature(vchSig);
1020 
1021  bool onlyVotingKeyAllowed = govObjType == GOVERNANCE_OBJECT_PROPOSAL && vote.GetSignal() == VOTE_SIGNAL_FUNDING;
1022 
1023  if (!vote.IsValid(onlyVotingKeyAllowed)) {
1024  throw JSONRPCError(RPC_INTERNAL_ERROR, "Failure to verify vote.");
1025  }
1026 
1027  CGovernanceException exception;
1028  if (governance.ProcessVoteAndRelay(vote, exception, *g_connman)) {
1029  return "Voted successfully";
1030  } else {
1031  throw JSONRPCError(RPC_INTERNAL_ERROR, "Error voting : " + exception.GetMessage());
1032  }
1033 }
1034 
1036 {
1037  if (request.fHelp || request.params.size() != 0) {
1038  throw std::runtime_error(
1039  "getgovernanceinfo\n"
1040  "Returns an object containing governance parameters.\n"
1041  "\nResult:\n"
1042  "{\n"
1043  " \"governanceminquorum\": xxxxx, (numeric) the absolute minimum number of votes needed to trigger a governance action\n"
1044  " \"proposalfee\": xxx.xx, (numeric) the collateral transaction fee which must be paid to create a proposal in " + CURRENCY_UNIT + "\n"
1045  " \"superblockcycle\": xxxxx, (numeric) the number of blocks between superblocks\n"
1046  " \"lastsuperblock\": xxxxx, (numeric) the block number of the last superblock\n"
1047  " \"nextsuperblock\": xxxxx, (numeric) the block number of the next superblock\n"
1048  "}\n"
1049  "\nExamples:\n"
1050  + HelpExampleCli("getgovernanceinfo", "")
1051  + HelpExampleRpc("getgovernanceinfo", "")
1052  );
1053  }
1054 
1055  LOCK(cs_main);
1056 
1057  int nLastSuperblock = 0, nNextSuperblock = 0;
1058  int nBlockHeight = chainActive.Height();
1059 
1060  CSuperblock::GetNearestSuperblocksHeights(nBlockHeight, nLastSuperblock, nNextSuperblock);
1061 
1062  UniValue obj(UniValue::VOBJ);
1063  obj.push_back(Pair("governanceminquorum", Params().GetConsensus().nGovernanceMinQuorum));
1065  obj.push_back(Pair("superblockcycle", Params().GetConsensus().nSuperblockCycle));
1066  obj.push_back(Pair("lastsuperblock", nLastSuperblock));
1067  obj.push_back(Pair("nextsuperblock", nNextSuperblock));
1068 
1069  return obj;
1070 }
1071 
1073 {
1074  if (request.fHelp || request.params.size() != 1) {
1075  throw std::runtime_error(
1076  "getsuperblockbudget index\n"
1077  "\nReturns the absolute maximum sum of superblock payments allowed.\n"
1078  "\nArguments:\n"
1079  "1. index (numeric, required) The block index\n"
1080  "\nResult:\n"
1081  "n (numeric) The absolute maximum sum of superblock payments allowed, in " + CURRENCY_UNIT + "\n"
1082  "\nExamples:\n"
1083  + HelpExampleCli("getsuperblockbudget", "1000")
1084  + HelpExampleRpc("getsuperblockbudget", "1000")
1085  );
1086  }
1087 
1088  int nBlockHeight = request.params[0].get_int();
1089  if (nBlockHeight < 0) {
1090  throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
1091  }
1092 
1093  return ValueFromAmount(CSuperblock::GetPaymentsLimit(nBlockHeight));
1094 }
1095 
1096 static const CRPCCommand commands[] =
1097 { // category name actor (function) argNames
1098  // --------------------- ------------------------ ----------------------- ----------
1099  /* Dash features */
1100  { "dash", "getgovernanceinfo", &getgovernanceinfo, {} },
1101  { "dash", "getsuperblockbudget", &getsuperblockbudget, {"index"} },
1102  { "dash", "gobject", &gobject, {} },
1103  { "dash", "voteraw", &voteraw, {"tx_hash","tx_index","gov_hash","signal","outcome","time","sig"} },
1104 
1105 };
1106 
1108 {
1109  for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
1110  t.appendCommand(commands[vcidx].name, &commands[vcidx]);
1111 }
UniValue ListObjects(const std::string &strCachedSignal, const std::string &strType, int nStartTime)
Definition: governance.cpp:623
void gobject_list_help()
Definition: governance.cpp:678
CTxMemPool mempool
CMasternodeSync masternodeSync
std::string GetDataAsHexString() const
GetData - As
std::vector< unsigned char > DecodeBase64(const char *p, bool *pfInvalid)
Governance Object.
Dash RPC command dispatcher.
Definition: server.h:140
UniValue gobject(const JSONRPCRequest &request)
Definition: governance.cpp:909
bool MasternodeRateCheck(const CGovernanceObject &govobj, bool fUpdateFailStatus=false)
Definition: governance.cpp:733
CCriticalSection cs_wallet
Definition: wallet.h:836
#define strprintf
Definition: tinyformat.h:1066
const uint256 & GetHash() const
Definition: wallet.h:272
int GetAbstainCount(vote_signal_enum_t eVoteSignalIn) const
int32_t ParseInt32V(const UniValue &v, const std::string &strName)
Definition: server.cpp:152
bool EnsureWalletIsAvailable(CWallet *const pwallet, bool avoidException)
Definition: rpcwallet.cpp:66
uint256 GetHash() const
void gobject_submit_help()
Definition: governance.cpp:233
static void GetNearestSuperblocksHeights(int nBlockHeight, int &nLastSuperblockRet, int &nNextSuperblockRet)
const COutPoint & GetMasternodeOutpoint() const
static const CAmount GOVERNANCE_PROPOSAL_FEE_TX
int Height() const
Return the maximal height in the chain.
Definition: chain.h:484
static const CRPCCommand commands[]
CCriticalSection cs_main
Definition: validation.cpp:213
UniValue ValueFromAmount(const CAmount &amount)
Definition: core_write.cpp:25
void SetMasternodeOutpoint(const COutPoint &outpoint)
const uint256 & GetCollateralHash() const
static const int GOVERNANCE_OBJECT_PROPOSAL
bool ProcessVoteAndRelay(const CGovernanceVote &vote, CGovernanceException &exception, CConnman &connman)
Definition: governance.h:381
const std::string & get_str() const
UniValue getsuperblockbudget(const JSONRPCRequest &request)
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: server.cpp:583
bool IsSetCachedFunding() const
const std::string CURRENCY_UNIT
Definition: feerate.cpp:10
std::shared_ptr< const CDeterministicMN > CDeterministicMNCPtr
int64_t get_int64() const
static vote_signal_enum_t ConvertVoteSignal(const std::string &strVoteSignal)
bool IsBlockchainSynced()
std::unique_ptr< CDeterministicMNManager > deterministicMNManager
bool appendCommand(const std::string &name, const CRPCCommand *pcmd)
Appends a CRPCCommand to the dispatch table.
Definition: server.cpp:353
bool IsSetCachedEndorsed() const
void AddPostponedObject(const CGovernanceObject &govobj)
Definition: governance.h:369
bool IsNull() const
Definition: uint256.h:33
std::string HelpRequiringPassphrase(CWallet *const pwallet)
Definition: rpcwallet.cpp:59
CGovernanceObject * FindGovernanceObject(const uint256 &nHash)
Definition: governance.cpp:463
Invalid, missing or duplicate parameter.
Definition: protocol.h:53
uint256 ParseHashV(const UniValue &v, std::string strName)
Utilities: convert hex-encoded Values (throws error if not hex).
Definition: server.cpp:121
bool IsValid() const
const std::string & GetErrorMessages()
void gobject_diff_help()
Definition: governance.cpp:711
CGovernanceManager governance
Definition: governance.cpp:23
int64_t GetTime()
Return system time (or mocked time, if set)
Definition: utiltime.cpp:22
#define LOCK2(cs1, cs2)
Definition: sync.h:179
void gobject_vote_conf_help()
Definition: governance.cpp:342
std::string name
Definition: server.h:132
void gobject_get_help()
Definition: governance.cpp:744
bool push_back(const UniValue &val)
Definition: univalue.cpp:110
#define LogPrintf(...)
Definition: util.h:203
int GetNoCount(vote_signal_enum_t eVoteSignalIn) const
CActiveMasternodeInfo activeMasternodeInfo
void AddGovernanceObject(CGovernanceObject &govobj, CConnman &connman, CNode *pfrom=nullptr)
Definition: governance.cpp:291
int GetObjectType() const
UniValue gobject_deserialize(const JSONRPCRequest &request)
Definition: governance.cpp:62
UniValue params
Definition: server.h:42
#define LOCK(cs)
Definition: sync.h:178
bool Sign(const CBLSSecretKey &key)
bool GetKey(const CKeyID &address, CKey &keyOut) const override
GetKey implementation that can derive a HD private key on the fly.
Definition: wallet.cpp:300
bool Validate(bool fCheckExpiration=true)
void Relay(CConnman &connman)
std::string GetRejectReason() const
Definition: validation.h:81
UniValue gobject_vote_conf(const JSONRPCRequest &request)
Definition: governance.cpp:354
bool IsSetCachedDelete() const
static const int GOVERNANCE_OBJECT_TRIGGER
std::string ToString() const
UniValue gobject_diff(const JSONRPCRequest &request)
Definition: governance.cpp:722
void gobject_count_help()
Definition: governance.cpp:25
vote_signal_enum_t GetSignal() const
A class which encapsulates information about a governance exception condition.
std::vector< const CGovernanceObject * > GetAllNewerThan(int64_t nMoreThanTime) const
Definition: governance.cpp:516
int get_int() const
std::string ToString() const
Definition: uint256.cpp:62
Invalid address or key.
Definition: protocol.h:51
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: server.cpp:578
void gobject_deserialize_help()
Definition: governance.cpp:52
static std::pair< std::string, UniValue > Pair(const char *cKey, const char *cVal)
Definition: univalue.h:185
UniValue gobject_getcurrentvotes(const JSONRPCRequest &request)
Definition: governance.cpp:842
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:26
void RegisterGovernanceRPCCommands(CRPCTable &t)
Register governance RPC commands.
bool isNull() const
Definition: univalue.h:78
std::vector< CGovernanceVote > GetCurrentVotes(const uint256 &nParentHash, const COutPoint &mnCollateralOutpointFilter) const
Definition: governance.cpp:472
CCriticalSection cs
Definition: txmempool.h:488
void gobject_getcurrentvotes_help()
Definition: governance.cpp:830
UniValue gobject_check(const JSONRPCRequest &request)
Definition: governance.cpp:88
int64_t GetCreationTime() const
void SetNull()
Definition: transaction.h:43
A transaction with a bunch of additional info that only the owner cares about.
Definition: wallet.h:280
void SetTime(int64_t nTimeIn)
#define LogPrint(category,...)
Definition: util.h:214
UniValue gobject_get(const JSONRPCRequest &request)
Definition: governance.cpp:754
bool IsValidLocally(std::string &strError, bool fCheckCollateral) const
bool fHelp
Definition: server.h:43
Capture information about block/transaction validation.
Definition: validation.h:22
256-bit opaque blob.
Definition: uint256.h:123
void SetSignature(const std::vector< unsigned char > &vchSigIn)
std::string GetDataAsPlainString() const
static CAmount GetPaymentsLimit(int nBlockHeight)
#define ARRAYLEN(array)
std::string EncodeDestination(const CTxDestination &dest)
Definition: base58.cpp:329
UniValue gobject_submit(const JSONRPCRequest &request)
Definition: governance.cpp:247
A key allocated from the key pool.
Definition: wallet.h:1273
const CChainParams & Params()
Return the currently selected parameters.
int GetAbsoluteYesCount(vote_signal_enum_t eVoteSignalIn) const
Get specific vote counts for each outcome (funding, validity, etc)
vote_outcome_enum_t
int64_t GetAdjustedTime()
Definition: timedata.cpp:35
int GetYesCount(vote_signal_enum_t eVoteSignalIn) const
UniValue gobject_list(const JSONRPCRequest &request)
Definition: governance.cpp:689
vote_signal_enum_t
int64_t atoi64(const char *psz)
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances...
Definition: wallet.h:715
std::unique_ptr< CConnman > g_connman
Definition: init.cpp:97
const std::string & GetMessage() const
const UniValue NullUniValue
Definition: univalue.cpp:15
CWallet * GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: rpcwallet.cpp:45
UniValue voteraw(const JSONRPCRequest &request)
Definition: governance.cpp:964
UniValue getgovernanceinfo(const JSONRPCRequest &request)
CCriticalSection cs
Definition: governance.h:278
std::unique_ptr< CBLSPublicKey > blsPubKeyOperator
UniValue JSONRPCError(int code, const std::string &message)
Definition: protocol.cpp:54
bool IsSetCachedValid() const
UniValue ToJson() const
size_t size() const
Definition: univalue.h:69
An encapsulated private key.
Definition: key.h:27
bool Sign(const CKey &key, const CKeyID &keyID)
UniValue VoteWithMasternodes(const std::map< uint256, CKey > &keys, const uint256 &hash, vote_signal_enum_t eVoteSignal, vote_outcome_enum_t eVoteOutcome)
Definition: governance.cpp:445
Still downloading initial blocks.
Definition: protocol.h:69
UniValue gobject_count(const JSONRPCRequest &request)
Definition: governance.cpp:35
CChain & chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:217
int64_t GetLastDiffTime() const
Definition: governance.h:353
std::unique_ptr< CBLSSecretKey > blsKeyOperator
void gobject_check_help()
Definition: governance.cpp:78
void gobject_help()
Definition: governance.cpp:882
int atoi(const std::string &str)
static vote_outcome_enum_t ConvertVoteOutcome(const std::string &strVoteOutcome)
void UpdateLastDiffTime(int64_t nTimeIn)
Definition: governance.h:354
bool GetBudgetSystemCollateralTX(CWalletTx &tx, uint256 hash, CAmount amount, const COutPoint &outpoint=COutPoint())
Definition: wallet.cpp:3631
void EnsureWalletIsUnlocked(CWallet *const pwallet)
Definition: rpcwallet.cpp:83
std::vector< unsigned char > ParseHex(const char *psz)
bool CommitTransaction(CWalletTx &wtxNew, CReserveKey &reservekey, CConnman *connman, CValidationState &state)
Call after CreateTransaction unless you want to abort.
Definition: wallet.cpp:4089
std::string ToStringShort() const
Definition: transaction.cpp:17
Released under the MIT license