Dash Core Source Documentation (0.14.0.2)

Find detailed information regarding the Dash Core source code.

rpcevo.cpp
Go to the documentation of this file.
1 // Copyright (c) 2018-2019 The Dash Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include "base58.h"
6 #include "consensus/validation.h"
7 #include "core_io.h"
8 #include "init.h"
9 #include "messagesigner.h"
10 #include "rpc/server.h"
11 #include "utilmoneystr.h"
12 #include "validation.h"
13 
14 #ifdef ENABLE_WALLET
15 #include "wallet/coincontrol.h"
16 #include "wallet/wallet.h"
17 #include "wallet/rpcwallet.h"
18 #endif//ENABLE_WALLET
19 
20 #include "netbase.h"
21 
22 #include "evo/specialtx.h"
23 #include "evo/providertx.h"
24 #include "evo/deterministicmns.h"
25 #include "evo/simplifiedmns.h"
26 
27 #include "bls/bls.h"
28 
29 #ifdef ENABLE_WALLET
30 extern UniValue signrawtransaction(const JSONRPCRequest& request);
31 extern UniValue sendrawtransaction(const JSONRPCRequest& request);
32 #endif//ENABLE_WALLET
33 
34 std::string GetHelpString(int nParamNum, std::string strParamName)
35 {
36  static const std::map<std::string, std::string> mapParamHelp = {
37  {"collateralAddress",
38  "%d. \"collateralAddress\" (string, required) The dash address to send the collateral to.\n"
39  },
40  {"collateralHash",
41  "%d. \"collateralHash\" (string, required) The collateral transaction hash.\n"
42  },
43  {"collateralIndex",
44  "%d. collateralIndex (numeric, required) The collateral transaction output index.\n"
45  },
46  {"feeSourceAddress",
47  "%d. \"feeSourceAddress\" (string, optional) If specified wallet will only use coins from this address to fund ProTx.\n"
48  " If not specified, payoutAddress is the one that is going to be used.\n"
49  " The private key belonging to this address must be known in your wallet.\n"
50  },
51  {"fundAddress",
52  "%d. \"fundAddress\" (string, optional) If specified wallet will only use coins from this address to fund ProTx.\n"
53  " If not specified, payoutAddress is the one that is going to be used.\n"
54  " The private key belonging to this address must be known in your wallet.\n"
55  },
56  {"ipAndPort",
57  "%d. \"ipAndPort\" (string, required) IP and port in the form \"IP:PORT\".\n"
58  " Must be unique on the network. Can be set to 0, which will require a ProUpServTx afterwards.\n"
59  },
60  {"operatorKey",
61  "%d. \"operatorKey\" (string, required) The operator private key belonging to the\n"
62  " registered operator public key.\n"
63  },
64  {"operatorPayoutAddress",
65  "%d. \"operatorPayoutAddress\" (string, optional) The address used for operator reward payments.\n"
66  " Only allowed when the ProRegTx had a non-zero operatorReward value.\n"
67  " If set to an empty string, the currently active payout address is reused.\n"
68  },
69  {"operatorPubKey",
70  "%d. \"operatorPubKey\" (string, required) The operator BLS public key. The private key does not have to be known.\n"
71  " It has to match the private key which is later used when operating the masternode.\n"
72  },
73  {"operatorReward",
74  "%d. \"operatorReward\" (numeric, required) The fraction in %% to share with the operator. The value must be\n"
75  " between 0.00 and 100.00.\n"
76  },
77  {"ownerAddress",
78  "%d. \"ownerAddress\" (string, required) The dash address to use for payee updates and proposal voting.\n"
79  " The private key belonging to this address must be known in your wallet. The address must\n"
80  " be unused and must differ from the collateralAddress\n"
81  },
82  {"payoutAddress",
83  "%d. \"payoutAddress\" (string, required) The dash address to use for masternode reward payments.\n"
84  },
85  {"proTxHash",
86  "%d. \"proTxHash\" (string, required) The hash of the initial ProRegTx.\n"
87  },
88  {"reason",
89  "%d. reason (numeric, optional) The reason for masternode service revocation.\n"
90  },
91  {"votingAddress",
92  "%d. \"votingAddress\" (string, required) The voting key address. The private key does not have to be known by your wallet.\n"
93  " It has to match the private key which is later used when voting on proposals.\n"
94  " If set to an empty string, ownerAddress will be used.\n"
95  },
96  };
97 
98  auto it = mapParamHelp.find(strParamName);
99  if (it == mapParamHelp.end())
100  throw std::runtime_error(strprintf("FIXME: WRONG PARAM NAME %s!", strParamName));
101 
102  return strprintf(it->second, nParamNum);
103 }
104 
105 // Allows to specify Dash address or priv key. In case of Dash address, the priv key is taken from the wallet
106 static CKey ParsePrivKey(CWallet* pwallet, const std::string &strKeyOrAddress, bool allowAddresses = true) {
107  CBitcoinAddress address;
108  if (allowAddresses && address.SetString(strKeyOrAddress) && address.IsValid()) {
109 #ifdef ENABLE_WALLET
110  if (!pwallet) {
111  throw std::runtime_error("addresses not supported when wallet is disabled");
112  }
113  EnsureWalletIsUnlocked(pwallet);
114  CKeyID keyId;
115  CKey key;
116  if (!address.GetKeyID(keyId) || !pwallet->GetKey(keyId, key))
117  throw std::runtime_error(strprintf("non-wallet or invalid address %s", strKeyOrAddress));
118  return key;
119 #else//ENABLE_WALLET
120  throw std::runtime_error("addresses not supported in no-wallet builds");
121 #endif//ENABLE_WALLET
122  }
123 
124  CBitcoinSecret secret;
125  if (!secret.SetString(strKeyOrAddress) || !secret.IsValid()) {
126  throw std::runtime_error(strprintf("invalid priv-key/address %s", strKeyOrAddress));
127  }
128  return secret.GetKey();
129 }
130 
131 static CKeyID ParsePubKeyIDFromAddress(const std::string& strAddress, const std::string& paramName)
132 {
133  CBitcoinAddress address(strAddress);
134  CKeyID keyID;
135  if (!address.IsValid() || !address.GetKeyID(keyID)) {
136  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be a valid P2PKH address, not %s", paramName, strAddress));
137  }
138  return keyID;
139 }
140 
141 static CBLSPublicKey ParseBLSPubKey(const std::string& hexKey, const std::string& paramName)
142 {
143  CBLSPublicKey pubKey;
144  if (!pubKey.SetHexStr(hexKey)) {
145  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be a valid BLS public key, not %s", paramName, hexKey));
146  }
147  return pubKey;
148 }
149 
150 static CBLSSecretKey ParseBLSSecretKey(const std::string& hexKey, const std::string& paramName)
151 {
152  CBLSSecretKey secKey;
153  if (!secKey.SetHexStr(hexKey)) {
154  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be a valid BLS secret key", paramName));
155  }
156  return secKey;
157 }
158 
159 #ifdef ENABLE_WALLET
160 
161 template<typename SpecialTxPayload>
162 static void FundSpecialTx(CWallet* pwallet, CMutableTransaction& tx, const SpecialTxPayload& payload, const CTxDestination& fundDest)
163 {
164  assert(pwallet != NULL);
165  LOCK2(cs_main, pwallet->cs_wallet);
166 
167  CTxDestination nodest = CNoDestination();
168  if (fundDest == nodest) {
169  throw JSONRPCError(RPC_INTERNAL_ERROR, "No source of funds specified");
170  }
171 
173  ds << payload;
174  tx.vExtraPayload.assign(ds.begin(), ds.end());
175 
176  static CTxOut dummyTxOut(0, CScript() << OP_RETURN);
177  std::vector<CRecipient> vecSend;
178  bool dummyTxOutAdded = false;
179 
180  if (tx.vout.empty()) {
181  // add dummy txout as CreateTransaction requires at least one recipient
182  tx.vout.emplace_back(dummyTxOut);
183  dummyTxOutAdded = true;
184  }
185 
186  for (const auto& txOut : tx.vout) {
187  CRecipient recipient = {txOut.scriptPubKey, txOut.nValue, false};
188  vecSend.push_back(recipient);
189  }
190 
191  CCoinControl coinControl;
192  coinControl.destChange = fundDest;
193  coinControl.fRequireAllInputs = false;
194 
195  std::vector<COutput> vecOutputs;
196  pwallet->AvailableCoins(vecOutputs);
197 
198  for (const auto& out : vecOutputs) {
199  CTxDestination txDest;
200  if (ExtractDestination(out.tx->tx->vout[out.i].scriptPubKey, txDest) && txDest == fundDest) {
201  coinControl.Select(COutPoint(out.tx->tx->GetHash(), out.i));
202  }
203  }
204 
205  if (!coinControl.HasSelected()) {
206  throw JSONRPCError(RPC_INTERNAL_ERROR, "No funds at specified address");
207  }
208 
209  CWalletTx wtx;
210  CReserveKey reservekey(pwallet);
211  CAmount nFee;
212  int nChangePos = -1;
213  std::string strFailReason;
214 
215  if (!pwallet->CreateTransaction(vecSend, wtx, reservekey, nFee, nChangePos, strFailReason, &coinControl, false, ALL_COINS, false, tx.vExtraPayload.size())) {
216  throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
217  }
218 
219  tx.vin = wtx.tx->vin;
220  tx.vout = wtx.tx->vout;
221 
222  if (dummyTxOutAdded && tx.vout.size() > 1) {
223  // CreateTransaction added a change output, so we don't need the dummy txout anymore.
224  // Removing it results in slight overpayment of fees, but we ignore this for now (as it's a very low amount).
225  auto it = std::find(tx.vout.begin(), tx.vout.end(), dummyTxOut);
226  assert(it != tx.vout.end());
227  tx.vout.erase(it);
228  }
229 }
230 
231 template<typename SpecialTxPayload>
232 static void UpdateSpecialTxInputsHash(const CMutableTransaction& tx, SpecialTxPayload& payload)
233 {
234  payload.inputsHash = CalcTxInputsHash(tx);
235 }
236 
237 template<typename SpecialTxPayload>
238 static void SignSpecialTxPayloadByHash(const CMutableTransaction& tx, SpecialTxPayload& payload, const CKey& key)
239 {
240  UpdateSpecialTxInputsHash(tx, payload);
241  payload.vchSig.clear();
242 
243  uint256 hash = ::SerializeHash(payload);
244  if (!CHashSigner::SignHash(hash, key, payload.vchSig)) {
245  throw JSONRPCError(RPC_INTERNAL_ERROR, "failed to sign special tx");
246  }
247 }
248 
249 template<typename SpecialTxPayload>
250 static void SignSpecialTxPayloadByString(const CMutableTransaction& tx, SpecialTxPayload& payload, const CKey& key)
251 {
252  UpdateSpecialTxInputsHash(tx, payload);
253  payload.vchSig.clear();
254 
255  std::string m = payload.MakeSignString();
256  if (!CMessageSigner::SignMessage(m, payload.vchSig, key)) {
257  throw JSONRPCError(RPC_INTERNAL_ERROR, "failed to sign special tx");
258  }
259 }
260 
261 template<typename SpecialTxPayload>
262 static void SignSpecialTxPayloadByHash(const CMutableTransaction& tx, SpecialTxPayload& payload, const CBLSSecretKey& key)
263 {
264  UpdateSpecialTxInputsHash(tx, payload);
265 
266  uint256 hash = ::SerializeHash(payload);
267  payload.sig = key.Sign(hash);
268 }
269 
270 static std::string SignAndSendSpecialTx(const CMutableTransaction& tx)
271 {
272  LOCK(cs_main);
273 
274  CValidationState state;
275  if (!CheckSpecialTx(tx, chainActive.Tip(), state)) {
276  throw std::runtime_error(FormatStateMessage(state));
277  }
278 
280  ds << tx;
281 
282  JSONRPCRequest signRequest;
283  signRequest.params.setArray();
284  signRequest.params.push_back(HexStr(ds.begin(), ds.end()));
285  UniValue signResult = signrawtransaction(signRequest);
286 
287  JSONRPCRequest sendRequest;
288  sendRequest.params.setArray();
289  sendRequest.params.push_back(signResult["hex"].get_str());
290  return sendrawtransaction(sendRequest).get_str();
291 }
292 
293 void protx_register_fund_help(CWallet* const pwallet)
294 {
295  throw std::runtime_error(
296  "protx register_fund \"collateralAddress\" \"ipAndPort\" \"ownerAddress\" \"operatorPubKey\" \"votingAddress\" operatorReward \"payoutAddress\" ( \"fundAddress\" )\n"
297  "\nCreates, funds and sends a ProTx to the network. The resulting transaction will move 1000 Dash\n"
298  "to the address specified by collateralAddress and will then function as the collateral of your\n"
299  "masternode.\n"
300  "A few of the limitations you see in the arguments are temporary and might be lifted after DIP3\n"
301  "is fully deployed.\n"
302  + HelpRequiringPassphrase(pwallet) + "\n"
303  "\nArguments:\n"
304  + GetHelpString(1, "collateralAddress")
305  + GetHelpString(2, "ipAndPort")
306  + GetHelpString(3, "ownerAddress")
307  + GetHelpString(4, "operatorPubKey")
308  + GetHelpString(5, "votingAddress")
309  + GetHelpString(6, "operatorReward")
310  + GetHelpString(7, "payoutAddress")
311  + GetHelpString(8, "fundAddress") +
312  "\nResult:\n"
313  "\"txid\" (string) The transaction id.\n"
314  "\nExamples:\n"
315  + HelpExampleCli("protx", "register_fund \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\" \"1.2.3.4:1234\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" \"93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\"")
316  );
317 }
318 
319 void protx_register_help(CWallet* const pwallet)
320 {
321  throw std::runtime_error(
322  "protx register \"collateralHash\" collateralIndex \"ipAndPort\" \"ownerAddress\" \"operatorPubKey\" \"votingAddress\" operatorReward \"payoutAddress\" ( \"feeSourceAddress\" )\n"
323  "\nSame as \"protx register_fund\", but with an externally referenced collateral.\n"
324  "The collateral is specified through \"collateralHash\" and \"collateralIndex\" and must be an unspent\n"
325  "transaction output spendable by this wallet. It must also not be used by any other masternode.\n"
326  + HelpRequiringPassphrase(pwallet) + "\n"
327  "\nArguments:\n"
328  + GetHelpString(1, "collateralHash")
329  + GetHelpString(2, "collateralIndex")
330  + GetHelpString(3, "ipAndPort")
331  + GetHelpString(4, "ownerAddress")
332  + GetHelpString(5, "operatorPubKey")
333  + GetHelpString(6, "votingAddress")
334  + GetHelpString(7, "operatorReward")
335  + GetHelpString(8, "payoutAddress")
336  + GetHelpString(9, "feeSourceAddress") +
337  "\nResult:\n"
338  "\"txid\" (string) The transaction id.\n"
339  "\nExamples:\n"
340  + HelpExampleCli("protx", "register \"0123456701234567012345670123456701234567012345670123456701234567\" 0 \"1.2.3.4:1234\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" \"93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\"")
341  );
342 }
343 
344 void protx_register_prepare_help()
345 {
346  throw std::runtime_error(
347  "protx register_prepare \"collateralHash\" collateralIndex \"ipAndPort\" \"ownerAddress\" \"operatorPubKey\" \"votingAddress\" operatorReward \"payoutAddress\" ( \"feeSourceAddress\" )\n"
348  "\nCreates an unsigned ProTx and returns it. The ProTx must be signed externally with the collateral\n"
349  "key and then passed to \"protx register_submit\". The prepared transaction will also contain inputs\n"
350  "and outputs to cover fees.\n"
351  "\nArguments:\n"
352  + GetHelpString(1, "collateralHash")
353  + GetHelpString(2, "collateralIndex")
354  + GetHelpString(3, "ipAndPort")
355  + GetHelpString(4, "ownerAddress")
356  + GetHelpString(5, "operatorPubKey")
357  + GetHelpString(6, "votingAddress")
358  + GetHelpString(7, "operatorReward")
359  + GetHelpString(8, "payoutAddress")
360  + GetHelpString(9, "feeSourceAddress") +
361  "\nResult:\n"
362  "{ (json object)\n"
363  " \"tx\" : (string) The serialized ProTx in hex format.\n"
364  " \"collateralAddress\" : (string) The collateral address.\n"
365  " \"signMessage\" : (string) The string message that needs to be signed with\n"
366  " the collateral key.\n"
367  "}\n"
368  "\nExamples:\n"
369  + HelpExampleCli("protx", "register_prepare \"0123456701234567012345670123456701234567012345670123456701234567\" 0 \"1.2.3.4:1234\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" \"93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\"")
370  );
371 }
372 
373 void protx_register_submit_help(CWallet* const pwallet)
374 {
375  throw std::runtime_error(
376  "protx register_submit \"tx\" \"sig\"\n"
377  "\nSubmits the specified ProTx to the network. This command will also sign the inputs of the transaction\n"
378  "which were previously added by \"protx register_prepare\" to cover transaction fees\n"
379  + HelpRequiringPassphrase(pwallet) + "\n"
380  "\nArguments:\n"
381  "1. \"tx\" (string, required) The serialized transaction previously returned by \"protx register_prepare\"\n"
382  "2. \"sig\" (string, required) The signature signed with the collateral key. Must be in base64 format.\n"
383  "\nResult:\n"
384  "\"txid\" (string) The transaction id.\n"
385  "\nExamples:\n"
386  + HelpExampleCli("protx", "register_submit \"tx\" \"sig\"")
387  );
388 }
389 
390 // handles register, register_prepare and register_fund in one method
391 UniValue protx_register(const JSONRPCRequest& request)
392 {
393  CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
394  bool isExternalRegister = request.params[0].get_str() == "register";
395  bool isFundRegister = request.params[0].get_str() == "register_fund";
396  bool isPrepareRegister = request.params[0].get_str() == "register_prepare";
397 
398  if (isFundRegister && (request.fHelp || (request.params.size() != 8 && request.params.size() != 9))) {
399  protx_register_fund_help(pwallet);
400  } else if (isExternalRegister && (request.fHelp || (request.params.size() != 9 && request.params.size() != 10))) {
401  protx_register_help(pwallet);
402  } else if (isPrepareRegister && (request.fHelp || (request.params.size() != 9 && request.params.size() != 10))) {
403  protx_register_prepare_help();
404  }
405 
406  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
407  return NullUniValue;
408 
409  if (isExternalRegister || isFundRegister) {
410  EnsureWalletIsUnlocked(pwallet);
411  }
412 
413  size_t paramIdx = 1;
414 
415  CAmount collateralAmount = 1000 * COIN;
416 
418  tx.nVersion = 3;
420 
421  CProRegTx ptx;
423 
424  if (isFundRegister) {
425  CBitcoinAddress collateralAddress(request.params[paramIdx].get_str());
426  if (!collateralAddress.IsValid()) {
427  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("invalid collaterall address: %s", request.params[paramIdx].get_str()));
428  }
429  CScript collateralScript = GetScriptForDestination(collateralAddress.Get());
430 
431  CTxOut collateralTxOut(collateralAmount, collateralScript);
432  tx.vout.emplace_back(collateralTxOut);
433 
434  paramIdx++;
435  } else {
436  uint256 collateralHash = ParseHashV(request.params[paramIdx], "collateralHash");
437  int32_t collateralIndex = ParseInt32V(request.params[paramIdx + 1], "collateralIndex");
438  if (collateralHash.IsNull() || collateralIndex < 0) {
439  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("invalid hash or index: %s-%d", collateralHash.ToString(), collateralIndex));
440  }
441 
442  ptx.collateralOutpoint = COutPoint(collateralHash, (uint32_t)collateralIndex);
443  paramIdx += 2;
444 
445  // TODO unlock on failure
446  LOCK(pwallet->cs_wallet);
447  pwallet->LockCoin(ptx.collateralOutpoint);
448  }
449 
450  if (request.params[paramIdx].get_str() != "") {
451  if (!Lookup(request.params[paramIdx].get_str().c_str(), ptx.addr, Params().GetDefaultPort(), false)) {
452  throw std::runtime_error(strprintf("invalid network address %s", request.params[paramIdx].get_str()));
453  }
454  }
455 
456  CKey keyOwner = ParsePrivKey(pwallet, request.params[paramIdx + 1].get_str(), true);
457  CBLSPublicKey pubKeyOperator = ParseBLSPubKey(request.params[paramIdx + 2].get_str(), "operator BLS address");
458  CKeyID keyIDVoting = keyOwner.GetPubKey().GetID();
459  if (request.params[paramIdx + 3].get_str() != "") {
460  keyIDVoting = ParsePubKeyIDFromAddress(request.params[paramIdx + 3].get_str(), "voting address");
461  }
462 
463  int64_t operatorReward;
464  if (!ParseFixedPoint(request.params[paramIdx + 4].getValStr(), 2, &operatorReward)) {
465  throw JSONRPCError(RPC_INVALID_PARAMETER, "operatorReward must be a number");
466  }
467  if (operatorReward < 0 || operatorReward > 10000) {
468  throw JSONRPCError(RPC_INVALID_PARAMETER, "operatorReward must be between 0.00 and 100.00");
469  }
470  ptx.nOperatorReward = operatorReward;
471 
472  CBitcoinAddress payoutAddress(request.params[paramIdx + 5].get_str());
473  if (!payoutAddress.IsValid()) {
474  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("invalid payout address: %s", request.params[paramIdx + 5].get_str()));
475  }
476 
477  ptx.keyIDOwner = keyOwner.GetPubKey().GetID();
478  ptx.pubKeyOperator = pubKeyOperator;
479  ptx.keyIDVoting = keyIDVoting;
480  ptx.scriptPayout = GetScriptForDestination(payoutAddress.Get());
481 
482  if (!isFundRegister) {
483  // make sure fee calculation works
484  ptx.vchSig.resize(65);
485  }
486 
487  CBitcoinAddress fundAddress = payoutAddress;
488  if (request.params.size() > paramIdx + 6) {
489  fundAddress = CBitcoinAddress(request.params[paramIdx + 6].get_str());
490  if (!fundAddress.IsValid())
491  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Dash address: ") + request.params[paramIdx + 6].get_str());
492  }
493 
494  FundSpecialTx(pwallet, tx, ptx, fundAddress.Get());
495  UpdateSpecialTxInputsHash(tx, ptx);
496 
497  if (isFundRegister) {
498  uint32_t collateralIndex = (uint32_t) -1;
499  for (uint32_t i = 0; i < tx.vout.size(); i++) {
500  if (tx.vout[i].nValue == collateralAmount) {
501  collateralIndex = i;
502  break;
503  }
504  }
505  assert(collateralIndex != (uint32_t) -1);
506  ptx.collateralOutpoint.n = collateralIndex;
507 
508  SetTxPayload(tx, ptx);
509  return SignAndSendSpecialTx(tx);
510  } else {
511  // referencing external collateral
512 
513  Coin coin;
514  if (!GetUTXOCoin(ptx.collateralOutpoint, coin)) {
515  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("collateral not found: %s", ptx.collateralOutpoint.ToStringShort()));
516  }
517  CTxDestination txDest;
518  CKeyID keyID;
519  if (!ExtractDestination(coin.out.scriptPubKey, txDest) || !CBitcoinAddress(txDest).GetKeyID(keyID)) {
520  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("collateral type not supported: %s", ptx.collateralOutpoint.ToStringShort()));
521  }
522 
523  if (isPrepareRegister) {
524  // external signing with collateral key
525  ptx.vchSig.clear();
526  SetTxPayload(tx, ptx);
527 
529  ret.push_back(Pair("tx", EncodeHexTx(tx)));
530  ret.push_back(Pair("collateralAddress", CBitcoinAddress(txDest).ToString()));
531  ret.push_back(Pair("signMessage", ptx.MakeSignString()));
532  return ret;
533  } else {
534  // lets prove we own the collateral
535  CKey key;
536  if (!pwallet->GetKey(keyID, key)) {
537  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("collateral key not in wallet: %s", CBitcoinAddress(keyID).ToString()));
538  }
539  SignSpecialTxPayloadByString(tx, ptx, key);
540  SetTxPayload(tx, ptx);
541  return SignAndSendSpecialTx(tx);
542  }
543  }
544 }
545 
546 UniValue protx_register_submit(const JSONRPCRequest& request)
547 {
548  CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
549  if (request.fHelp || request.params.size() != 3) {
550  protx_register_submit_help(pwallet);
551  }
552 
553  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
554  return NullUniValue;
555 
556  EnsureWalletIsUnlocked(pwallet);
557 
559  if (!DecodeHexTx(tx, request.params[1].get_str())) {
560  throw JSONRPCError(RPC_INVALID_PARAMETER, "transaction not deserializable");
561  }
563  throw JSONRPCError(RPC_INVALID_PARAMETER, "transaction not a ProRegTx");
564  }
565  CProRegTx ptx;
566  if (!GetTxPayload(tx, ptx)) {
567  throw JSONRPCError(RPC_INVALID_PARAMETER, "transaction payload not deserializable");
568  }
569  if (!ptx.vchSig.empty()) {
570  throw JSONRPCError(RPC_INVALID_PARAMETER, "payload signature not empty");
571  }
572 
573  ptx.vchSig = DecodeBase64(request.params[2].get_str().c_str());
574 
575  SetTxPayload(tx, ptx);
576  return SignAndSendSpecialTx(tx);
577 }
578 
579 void protx_update_service_help(CWallet* const pwallet)
580 {
581  throw std::runtime_error(
582  "protx update_service \"proTxHash\" \"ipAndPort\" \"operatorKey\" (\"operatorPayoutAddress\" \"feeSourceAddress\" )\n"
583  "\nCreates and sends a ProUpServTx to the network. This will update the IP address\n"
584  "of a masternode.\n"
585  "If this is done for a masternode that got PoSe-banned, the ProUpServTx will also revive this masternode.\n"
586  + HelpRequiringPassphrase(pwallet) + "\n"
587  "\nArguments:\n"
588  + GetHelpString(1, "proTxHash")
589  + GetHelpString(2, "ipAndPort")
590  + GetHelpString(3, "operatorKey")
591  + GetHelpString(4, "operatorPayoutAddress")
592  + GetHelpString(5, "feeSourceAddress") +
593  "\nResult:\n"
594  "\"txid\" (string) The transaction id.\n"
595  "\nExamples:\n"
596  + HelpExampleCli("protx", "update_service \"0123456701234567012345670123456701234567012345670123456701234567\" \"1.2.3.4:1234\" 5a2e15982e62f1e0b7cf9783c64cf7e3af3f90a52d6c40f6f95d624c0b1621cd")
597  );
598 }
599 
600 UniValue protx_update_service(const JSONRPCRequest& request)
601 {
602  CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
603  if (request.fHelp || (request.params.size() < 4 || request.params.size() > 6))
604  protx_update_service_help(pwallet);
605 
606  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
607  return NullUniValue;
608 
609  EnsureWalletIsUnlocked(pwallet);
610 
611  CProUpServTx ptx;
613  ptx.proTxHash = ParseHashV(request.params[1], "proTxHash");
614 
615  if (!Lookup(request.params[2].get_str().c_str(), ptx.addr, Params().GetDefaultPort(), false)) {
616  throw std::runtime_error(strprintf("invalid network address %s", request.params[2].get_str()));
617  }
618 
619  CBLSSecretKey keyOperator = ParseBLSSecretKey(request.params[3].get_str(), "operatorKey");
620 
622  if (!dmn) {
623  throw std::runtime_error(strprintf("masternode with proTxHash %s not found", ptx.proTxHash.ToString()));
624  }
625 
626  if (keyOperator.GetPublicKey() != dmn->pdmnState->pubKeyOperator.Get()) {
627  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("the operator key does not belong to the registered public key"));
628  }
629 
631  tx.nVersion = 3;
633 
634  // param operatorPayoutAddress
635  if (request.params.size() >= 5) {
636  if (request.params[4].get_str().empty()) {
637  ptx.scriptOperatorPayout = dmn->pdmnState->scriptOperatorPayout;
638  } else {
639  CBitcoinAddress payoutAddress(request.params[4].get_str());
640  if (!payoutAddress.IsValid()) {
641  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("invalid operator payout address: %s", request.params[4].get_str()));
642  }
643  ptx.scriptOperatorPayout = GetScriptForDestination(payoutAddress.Get());
644  }
645  } else {
646  ptx.scriptOperatorPayout = dmn->pdmnState->scriptOperatorPayout;
647  }
648 
649  CTxDestination feeSource;
650 
651  // param feeSourceAddress
652  if (request.params.size() >= 6) {
653  CBitcoinAddress feeSourceAddress = CBitcoinAddress(request.params[5].get_str());
654  if (!feeSourceAddress.IsValid())
655  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Dash address: ") + request.params[5].get_str());
656  feeSource = feeSourceAddress.Get();
657  } else {
658  if (ptx.scriptOperatorPayout != CScript()) {
659  // use operator reward address as default source for fees
661  } else {
662  // use payout address as default source for fees
663  ExtractDestination(dmn->pdmnState->scriptPayout, feeSource);
664  }
665  }
666 
667  FundSpecialTx(pwallet, tx, ptx, feeSource);
668 
669  SignSpecialTxPayloadByHash(tx, ptx, keyOperator);
670  SetTxPayload(tx, ptx);
671 
672  return SignAndSendSpecialTx(tx);
673 }
674 
675 void protx_update_registrar_help(CWallet* const pwallet)
676 {
677  throw std::runtime_error(
678  "protx update_registrar \"proTxHash\" \"operatorPubKey\" \"votingAddress\" \"payoutAddress\" ( \"feeSourceAddress\" )\n"
679  "\nCreates and sends a ProUpRegTx to the network. This will update the operator key, voting key and payout\n"
680  "address of the masternode specified by \"proTxHash\".\n"
681  "The owner key of the masternode must be known to your wallet.\n"
682  + HelpRequiringPassphrase(pwallet) + "\n"
683  "\nArguments:\n"
684  + GetHelpString(1, "proTxHash")
685  + GetHelpString(2, "operatorPubKey")
686  + GetHelpString(3, "votingAddress")
687  + GetHelpString(4, "payoutAddress")
688  + GetHelpString(5, "feeSourceAddress") +
689  "\nResult:\n"
690  "\"txid\" (string) The transaction id.\n"
691  "\nExamples:\n"
692  + HelpExampleCli("protx", "update_registrar \"0123456701234567012345670123456701234567012345670123456701234567\" \"982eb34b7c7f614f29e5c665bc3605f1beeef85e3395ca12d3be49d2868ecfea5566f11cedfad30c51b2403f2ad95b67\" \"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\"")
693  );
694 }
695 
696 UniValue protx_update_registrar(const JSONRPCRequest& request)
697 {
698  CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
699  if (request.fHelp || (request.params.size() != 5 && request.params.size() != 6)) {
700  protx_update_registrar_help(pwallet);
701  }
702 
703  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
704  return NullUniValue;
705 
706  EnsureWalletIsUnlocked(pwallet);
707 
708  CProUpRegTx ptx;
710  ptx.proTxHash = ParseHashV(request.params[1], "proTxHash");
711 
713  if (!dmn) {
714  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("masternode %s not found", ptx.proTxHash.ToString()));
715  }
716  ptx.pubKeyOperator = dmn->pdmnState->pubKeyOperator.Get();
717  ptx.keyIDVoting = dmn->pdmnState->keyIDVoting;
718  ptx.scriptPayout = dmn->pdmnState->scriptPayout;
719 
720  if (request.params[2].get_str() != "") {
721  ptx.pubKeyOperator = ParseBLSPubKey(request.params[2].get_str(), "operator BLS address");
722  }
723  if (request.params[3].get_str() != "") {
724  ptx.keyIDVoting = ParsePubKeyIDFromAddress(request.params[3].get_str(), "voting address");
725  }
726 
727  CBitcoinAddress payoutAddress(request.params[4].get_str());
728  if (!payoutAddress.IsValid()) {
729  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("invalid payout address: %s", request.params[4].get_str()));
730  }
731  ptx.scriptPayout = GetScriptForDestination(payoutAddress.Get());
732 
733  CKey keyOwner;
734  if (!pwallet->GetKey(dmn->pdmnState->keyIDOwner, keyOwner)) {
735  throw std::runtime_error(strprintf("Private key for owner address %s not found in your wallet", CBitcoinAddress(dmn->pdmnState->keyIDOwner).ToString()));
736  }
737 
739  tx.nVersion = 3;
741 
742  // make sure we get anough fees added
743  ptx.vchSig.resize(65);
744 
745  CBitcoinAddress feeSourceAddress = payoutAddress;
746  if (request.params.size() > 5) {
747  feeSourceAddress = CBitcoinAddress(request.params[5].get_str());
748  if (!feeSourceAddress.IsValid())
749  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Dash address: ") + request.params[5].get_str());
750  }
751 
752  FundSpecialTx(pwallet, tx, ptx, feeSourceAddress.Get());
753  SignSpecialTxPayloadByHash(tx, ptx, keyOwner);
754  SetTxPayload(tx, ptx);
755 
756  return SignAndSendSpecialTx(tx);
757 }
758 
759 void protx_revoke_help(CWallet* const pwallet)
760 {
761  throw std::runtime_error(
762  "protx revoke \"proTxHash\" \"operatorKey\" ( reason \"feeSourceAddress\")\n"
763  "\nCreates and sends a ProUpRevTx to the network. This will revoke the operator key of the masternode and\n"
764  "put it into the PoSe-banned state. It will also set the service field of the masternode\n"
765  "to zero. Use this in case your operator key got compromised or you want to stop providing your service\n"
766  "to the masternode owner.\n"
767  + HelpRequiringPassphrase(pwallet) + "\n"
768  "\nArguments:\n"
769  + GetHelpString(1, "proTxHash")
770  + GetHelpString(2, "operatorKey")
771  + GetHelpString(3, "reason")
772  + GetHelpString(4, "feeSourceAddress") +
773  "\nResult:\n"
774  "\"txid\" (string) The transaction id.\n"
775  "\nExamples:\n"
776  + HelpExampleCli("protx", "revoke \"0123456701234567012345670123456701234567012345670123456701234567\" \"072f36a77261cdd5d64c32d97bac417540eddca1d5612f416feb07ff75a8e240\"")
777  );
778 }
779 
780 UniValue protx_revoke(const JSONRPCRequest& request)
781 {
782  CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
783  if (request.fHelp || (request.params.size() < 3 || request.params.size() > 5)) {
784  protx_revoke_help(pwallet);
785  }
786 
787  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
788  return NullUniValue;
789 
790  EnsureWalletIsUnlocked(pwallet);
791 
792  CProUpRevTx ptx;
794  ptx.proTxHash = ParseHashV(request.params[1], "proTxHash");
795 
796  CBLSSecretKey keyOperator = ParseBLSSecretKey(request.params[2].get_str(), "operatorKey");
797 
798  if (request.params.size() > 3) {
799  int32_t nReason = ParseInt32V(request.params[3], "reason");
800  if (nReason < 0 || nReason > CProUpRevTx::REASON_LAST) {
801  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("invalid reason %d, must be between 0 and %d", nReason, CProUpRevTx::REASON_LAST));
802  }
803  ptx.nReason = (uint16_t)nReason;
804  }
805 
807  if (!dmn) {
808  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("masternode %s not found", ptx.proTxHash.ToString()));
809  }
810 
811  if (keyOperator.GetPublicKey() != dmn->pdmnState->pubKeyOperator.Get()) {
812  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("the operator key does not belong to the registered public key"));
813  }
814 
816  tx.nVersion = 3;
818 
819  if (request.params.size() > 4) {
820  CBitcoinAddress feeSourceAddress = CBitcoinAddress(request.params[4].get_str());
821  if (!feeSourceAddress.IsValid())
822  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Dash address: ") + request.params[4].get_str());
823  FundSpecialTx(pwallet, tx, ptx, feeSourceAddress.Get());
824  } else if (dmn->pdmnState->scriptOperatorPayout != CScript()) {
825  // Using funds from previousely specified operator payout address
826  CTxDestination txDest;
827  ExtractDestination(dmn->pdmnState->scriptOperatorPayout, txDest);
828  FundSpecialTx(pwallet, tx, ptx, txDest);
829  } else if (dmn->pdmnState->scriptPayout != CScript()) {
830  // Using funds from previousely specified masternode payout address
831  CTxDestination txDest;
832  ExtractDestination(dmn->pdmnState->scriptPayout, txDest);
833  FundSpecialTx(pwallet, tx, ptx, txDest);
834  } else {
835  throw JSONRPCError(RPC_INTERNAL_ERROR, "No payout or fee source addresses found, can't revoke");
836  }
837 
838  SignSpecialTxPayloadByHash(tx, ptx, keyOperator);
839  SetTxPayload(tx, ptx);
840 
841  return SignAndSendSpecialTx(tx);
842 }
843 #endif//ENABLE_WALLET
844 
846 {
847  throw std::runtime_error(
848  "protx list (\"type\" \"detailed\" \"height\")\n"
849  "\nLists all ProTxs in your wallet or on-chain, depending on the given type.\n"
850  "If \"type\" is not specified, it defaults to \"registered\".\n"
851  "If \"detailed\" is not specified, it defaults to \"false\" and only the hashes of the ProTx will be returned.\n"
852  "If \"height\" is not specified, it defaults to the current chain-tip.\n"
853  "\nAvailable types:\n"
854  " registered - List all ProTx which are registered at the given chain height.\n"
855  " This will also include ProTx which failed PoSe verfication.\n"
856  " valid - List only ProTx which are active/valid at the given chain height.\n"
857 #ifdef ENABLE_WALLET
858  " wallet - List only ProTx which are found in your wallet at the given chain height.\n"
859  " This will also include ProTx which failed PoSe verfication.\n"
860 #endif
861  );
862 }
863 
864 static bool CheckWalletOwnsKey(CWallet* pwallet, const CKeyID& keyID) {
865 #ifndef ENABLE_WALLET
866  return false;
867 #else
868  if (!pwallet) {
869  return false;
870  }
871  return pwallet->HaveKey(keyID);
872 #endif
873 }
874 
875 static bool CheckWalletOwnsScript(CWallet* pwallet, const CScript& script) {
876 #ifndef ENABLE_WALLET
877  return false;
878 #else
879  if (!pwallet) {
880  return false;
881  }
882 
883  CTxDestination dest;
884  if (ExtractDestination(script, dest)) {
885  if ((boost::get<CKeyID>(&dest) && pwallet->HaveKey(*boost::get<CKeyID>(&dest))) || (boost::get<CScriptID>(&dest) && pwallet->HaveCScript(*boost::get<CScriptID>(&dest)))) {
886  return true;
887  }
888  }
889  return false;
890 #endif
891 }
892 
893 UniValue BuildDMNListEntry(CWallet* pwallet, const CDeterministicMNCPtr& dmn, bool detailed)
894 {
895  if (!detailed) {
896  return dmn->proTxHash.ToString();
897  }
898 
900 
901  dmn->ToJson(o);
902 
903  int confirmations = GetUTXOConfirmations(dmn->collateralOutpoint);
904  o.push_back(Pair("confirmations", confirmations));
905 
906  bool hasOwnerKey = CheckWalletOwnsKey(pwallet, dmn->pdmnState->keyIDOwner);
907  bool hasOperatorKey = false; //CheckWalletOwnsKey(dmn->pdmnState->keyIDOperator);
908  bool hasVotingKey = CheckWalletOwnsKey(pwallet, dmn->pdmnState->keyIDVoting);
909 
910  bool ownsCollateral = false;
911  CTransactionRef collateralTx;
912  uint256 tmpHashBlock;
913  if (GetTransaction(dmn->collateralOutpoint.hash, collateralTx, Params().GetConsensus(), tmpHashBlock)) {
914  ownsCollateral = CheckWalletOwnsScript(pwallet, collateralTx->vout[dmn->collateralOutpoint.n].scriptPubKey);
915  }
916 
917  UniValue walletObj(UniValue::VOBJ);
918  walletObj.push_back(Pair("hasOwnerKey", hasOwnerKey));
919  walletObj.push_back(Pair("hasOperatorKey", hasOperatorKey));
920  walletObj.push_back(Pair("hasVotingKey", hasVotingKey));
921  walletObj.push_back(Pair("ownsCollateral", ownsCollateral));
922  walletObj.push_back(Pair("ownsPayeeScript", CheckWalletOwnsScript(pwallet, dmn->pdmnState->scriptPayout)));
923  walletObj.push_back(Pair("ownsOperatorRewardScript", CheckWalletOwnsScript(pwallet, dmn->pdmnState->scriptOperatorPayout)));
924  o.push_back(Pair("wallet", walletObj));
925 
926  return o;
927 }
928 
930 {
931  if (request.fHelp) {
932  protx_list_help();
933  }
934 
935 #ifdef ENABLE_WALLET
936  CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
937 #else
938  CWallet* const pwallet = nullptr;
939 #endif
940 
941  std::string type = "registered";
942  if (request.params.size() > 1) {
943  type = request.params[1].get_str();
944  }
945 
947 
948  LOCK(cs_main);
949 
950  if (type == "wallet") {
951  if (!pwallet) {
952  throw std::runtime_error("\"protx list wallet\" not supported when wallet is disabled");
953  }
954 #ifdef ENABLE_WALLET
955  LOCK2(cs_main, pwallet->cs_wallet);
956 
957  if (request.params.size() > 3) {
958  protx_list_help();
959  }
960 
961  bool detailed = request.params.size() > 2 ? ParseBoolV(request.params[2], "detailed") : false;
962 
963  int height = request.params.size() > 3 ? ParseInt32V(request.params[3], "height") : chainActive.Height();
964  if (height < 1 || height > chainActive.Height()) {
965  throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid height specified");
966  }
967 
968  std::vector<COutPoint> vOutpts;
969  pwallet->ListProTxCoins(vOutpts);
970  std::set<COutPoint> setOutpts;
971  for (const auto& outpt : vOutpts) {
972  setOutpts.emplace(outpt);
973  }
974 
976  mnList.ForEachMN(false, [&](const CDeterministicMNCPtr& dmn) {
977  if (setOutpts.count(dmn->collateralOutpoint) ||
978  CheckWalletOwnsKey(pwallet, dmn->pdmnState->keyIDOwner) ||
979  CheckWalletOwnsKey(pwallet, dmn->pdmnState->keyIDVoting) ||
980  CheckWalletOwnsScript(pwallet, dmn->pdmnState->scriptPayout) ||
981  CheckWalletOwnsScript(pwallet, dmn->pdmnState->scriptOperatorPayout)) {
982  ret.push_back(BuildDMNListEntry(pwallet, dmn, detailed));
983  }
984  });
985 #endif
986  } else if (type == "valid" || type == "registered") {
987  if (request.params.size() > 4) {
988  protx_list_help();
989  }
990 
991  LOCK(cs_main);
992 
993  bool detailed = request.params.size() > 2 ? ParseBoolV(request.params[2], "detailed") : false;
994 
995  int height = request.params.size() > 3 ? ParseInt32V(request.params[3], "height") : chainActive.Height();
996  if (height < 1 || height > chainActive.Height()) {
997  throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid height specified");
998  }
999 
1001  bool onlyValid = type == "valid";
1002  mnList.ForEachMN(onlyValid, [&](const CDeterministicMNCPtr& dmn) {
1003  ret.push_back(BuildDMNListEntry(pwallet, dmn, detailed));
1004  });
1005  } else {
1006  throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid type specified");
1007  }
1008 
1009  return ret;
1010 }
1011 
1013 {
1014  throw std::runtime_error(
1015  "protx info \"proTxHash\"\n"
1016  "\nReturns detailed information about a deterministic masternode.\n"
1017  "\nArguments:\n"
1018  + GetHelpString(1, "proTxHash") +
1019  "\nResult:\n"
1020  "{ (json object) Details about a specific deterministic masternode\n"
1021  "}\n"
1022  "\nExamples:\n"
1023  + HelpExampleCli("protx", "info \"0123456701234567012345670123456701234567012345670123456701234567\"")
1024  );
1025 }
1026 
1028 {
1029  if (request.fHelp || request.params.size() != 2) {
1030  protx_info_help();
1031  }
1032 
1033 #ifdef ENABLE_WALLET
1034  CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
1035 #else
1036  CWallet* const pwallet = nullptr;
1037 #endif
1038 
1039  uint256 proTxHash = ParseHashV(request.params[1], "proTxHash");
1040  auto mnList = deterministicMNManager->GetListAtChainTip();
1041  auto dmn = mnList.GetMN(proTxHash);
1042  if (!dmn) {
1043  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s not found", proTxHash.ToString()));
1044  }
1045  return BuildDMNListEntry(pwallet, dmn, true);
1046 }
1047 
1049 {
1050  throw std::runtime_error(
1051  "protx diff \"baseBlock\" \"block\"\n"
1052  "\nCalculates a diff between two deterministic masternode lists. The result also contains proof data.\n"
1053  "\nArguments:\n"
1054  "1. \"baseBlock\" (numeric, required) The starting block height.\n"
1055  "2. \"block\" (numeric, required) The ending block height.\n"
1056  );
1057 }
1058 
1059 static uint256 ParseBlock(const UniValue& v, std::string strName)
1060 {
1062 
1063  try {
1064  return ParseHashV(v, strName);
1065  } catch (...) {
1066  int h = ParseInt32V(v, strName);
1067  if (h < 1 || h > chainActive.Height())
1068  throw std::runtime_error(strprintf("%s must be a block hash or chain height and not %s", strName, v.getValStr()));
1069  return *chainActive[h]->phashBlock;
1070  }
1071 }
1072 
1074 {
1075  if (request.fHelp || request.params.size() != 3) {
1076  protx_diff_help();
1077  }
1078 
1079  LOCK(cs_main);
1080  uint256 baseBlockHash = ParseBlock(request.params[1], "baseBlock");
1081  uint256 blockHash = ParseBlock(request.params[2], "block");
1082 
1083  CSimplifiedMNListDiff mnListDiff;
1084  std::string strError;
1085  if (!BuildSimplifiedMNListDiff(baseBlockHash, blockHash, mnListDiff, strError)) {
1086  throw std::runtime_error(strError);
1087  }
1088 
1089  UniValue ret;
1090  mnListDiff.ToJson(ret);
1091  return ret;
1092 }
1093 
1094 [[ noreturn ]] void protx_help()
1095 {
1096  throw std::runtime_error(
1097  "protx \"command\" ...\n"
1098  "Set of commands to execute ProTx related actions.\n"
1099  "To get help on individual commands, use \"help protx command\".\n"
1100  "\nArguments:\n"
1101  "1. \"command\" (string, required) The command to execute\n"
1102  "\nAvailable commands:\n"
1103 #ifdef ENABLE_WALLET
1104  " register - Create and send ProTx to network\n"
1105  " register_fund - Fund, create and send ProTx to network\n"
1106  " register_prepare - Create an unsigned ProTx\n"
1107  " register_submit - Sign and submit a ProTx\n"
1108 #endif
1109  " list - List ProTxs\n"
1110  " info - Return information about a ProTx\n"
1111 #ifdef ENABLE_WALLET
1112  " update_service - Create and send ProUpServTx to network\n"
1113  " update_registrar - Create and send ProUpRegTx to network\n"
1114  " revoke - Create and send ProUpRevTx to network\n"
1115 #endif
1116  " diff - Calculate a diff and a proof between two masternode lists\n"
1117  );
1118 }
1119 
1121 {
1122  if (request.fHelp && request.params.empty()) {
1123  protx_help();
1124  }
1125 
1126  std::string command;
1127  if (request.params.size() >= 1) {
1128  command = request.params[0].get_str();
1129  }
1130 
1131 #ifdef ENABLE_WALLET
1132  if (command == "register" || command == "register_fund" || command == "register_prepare") {
1133  return protx_register(request);
1134  } else if (command == "register_submit") {
1135  return protx_register_submit(request);
1136  } else if (command == "update_service") {
1137  return protx_update_service(request);
1138  } else if (command == "update_registrar") {
1139  return protx_update_registrar(request);
1140  } else if (command == "revoke") {
1141  return protx_revoke(request);
1142  } else
1143 #endif
1144  if (command == "list") {
1145  return protx_list(request);
1146  } else if (command == "info") {
1147  return protx_info(request);
1148  } else if (command == "diff") {
1149  return protx_diff(request);
1150  } else {
1151  protx_help();
1152  }
1153 }
1154 
1156 {
1157  throw std::runtime_error(
1158  "bls generate\n"
1159  "\nReturns a BLS secret/public key pair.\n"
1160  "\nResult:\n"
1161  "{\n"
1162  " \"secret\": \"xxxx\", (string) BLS secret key\n"
1163  " \"public\": \"xxxx\", (string) BLS public key\n"
1164  "}\n"
1165  "\nExamples:\n"
1166  + HelpExampleCli("bls generate", "")
1167  );
1168 }
1169 
1171 {
1172  if (request.fHelp || request.params.size() != 1) {
1174  }
1175 
1176  CBLSSecretKey sk;
1177  sk.MakeNewKey();
1178 
1179  UniValue ret(UniValue::VOBJ);
1180  ret.push_back(Pair("secret", sk.ToString()));
1181  ret.push_back(Pair("public", sk.GetPublicKey().ToString()));
1182  return ret;
1183 }
1184 
1186 {
1187  throw std::runtime_error(
1188  "bls fromsecret \"secret\"\n"
1189  "\nParses a BLS secret key and returns the secret/public key pair.\n"
1190  "\nArguments:\n"
1191  "1. \"secret\" (string, required) The BLS secret key\n"
1192  "\nResult:\n"
1193  "{\n"
1194  " \"secret\": \"xxxx\", (string) BLS secret key\n"
1195  " \"public\": \"xxxx\", (string) BLS public key\n"
1196  "}\n"
1197  "\nExamples:\n"
1198  + HelpExampleCli("bls fromsecret", "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")
1199  );
1200 }
1201 
1203 {
1204  if (request.fHelp || request.params.size() != 2) {
1206  }
1207 
1208  CBLSSecretKey sk;
1209  if (!sk.SetHexStr(request.params[1].get_str())) {
1210  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Secret key must be a valid hex string of length %d", sk.SerSize*2));
1211  }
1212 
1213  UniValue ret(UniValue::VOBJ);
1214  ret.push_back(Pair("secret", sk.ToString()));
1215  ret.push_back(Pair("public", sk.GetPublicKey().ToString()));
1216  return ret;
1217 }
1218 
1219 [[ noreturn ]] void bls_help()
1220 {
1221  throw std::runtime_error(
1222  "bls \"command\" ...\n"
1223  "Set of commands to execute BLS related actions.\n"
1224  "To get help on individual commands, use \"help bls command\".\n"
1225  "\nArguments:\n"
1226  "1. \"command\" (string, required) The command to execute\n"
1227  "\nAvailable commands:\n"
1228  " generate - Create a BLS secret/public key pair\n"
1229  " fromsecret - Parse a BLS secret key and return the secret/public key pair\n"
1230  );
1231 }
1232 
1234 {
1235  if (request.fHelp && request.params.empty()) {
1236  bls_help();
1237  }
1238 
1239  std::string command;
1240  if (request.params.size() >= 1) {
1241  command = request.params[0].get_str();
1242  }
1243 
1244  if (command == "generate") {
1245  return bls_generate(request);
1246  } else if (command == "fromsecret") {
1247  return bls_fromsecret(request);
1248  } else {
1249  bls_help();
1250  }
1251 }
1252 
1253 static const CRPCCommand commands[] =
1254 { // category name actor (function) okSafeMode
1255  // --------------------- ------------------------ ----------------------- ----------
1256  { "evo", "bls", &_bls, false, {} },
1257  { "evo", "protx", &protx, false, {} },
1258 };
1259 
1261 {
1262  for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) {
1263  tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
1264  }
1265 }
bool GetTxPayload(const std::vector< unsigned char > &payload, T &obj)
Definition: specialtx.h:21
CDeterministicMNList GetListAtChainTip()
bool GetBlockHash(uint256 &hashRet, int nBlockHeight)
Return true if hash can be found in chainActive at nBlockHeight height.
uint256 proTxHash
Definition: providertx.h:108
void bls_fromsecret_help()
Definition: rpcevo.cpp:1185
bool IsValid() const
Definition: base58.cpp:247
uint256 proTxHash
Definition: providertx.h:74
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:69
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Definition: standard.cpp:162
static uint256 ParseBlock(const UniValue &v, std::string strName)
Definition: rpcevo.cpp:1059
CKeyID keyIDVoting
Definition: providertx.h:111
std::vector< unsigned char > DecodeBase64(const char *p, bool *pfInvalid)
bool BuildSimplifiedMNListDiff(const uint256 &baseBlockHash, const uint256 &blockHash, CSimplifiedMNListDiff &mnListDiffRet, std::string &errorRet)
Dash RPC command dispatcher.
Definition: server.h:148
CScript scriptPubKey
Definition: transaction.h:148
std::vector< unsigned char > vchSig
Definition: providertx.h:35
void ToJson(UniValue &obj) const
COutPoint collateralOutpoint
Definition: providertx.h:27
CKey GetKey()
Definition: base58.cpp:314
A UTXO entry.
Definition: coins.h:27
void protx_list_help()
Definition: rpcevo.cpp:845
CDeterministicMNCPtr GetMN(const uint256 &proTxHash) const
CCriticalSection cs_wallet
Definition: wallet.h:747
UniValue protx_list(const JSONRPCRequest &request)
Definition: rpcevo.cpp:929
#define strprintf
Definition: tinyformat.h:1047
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:155
int32_t ParseInt32V(const UniValue &v, const std::string &strName)
Definition: server.cpp:172
bool EnsureWalletIsAvailable(CWallet *const pwallet, bool avoidException)
Definition: rpcwallet.cpp:46
std::vector< CTxIn > vin
Definition: transaction.h:316
static const CAmount COIN
Definition: amount.h:17
virtual bool HaveCScript(const CScriptID &hash) const override
Definition: keystore.cpp:51
bool SetHexStr(const std::string &str)
Definition: bls.h:157
static bool SignHash(const uint256 &hash, const CKey &key, std::vector< unsigned char > &vchSigRet)
Sign the hash, returns true if successful.
int Height() const
Return the maximal height in the chain.
Definition: chain.h:481
CCriticalSection cs_main
Global state.
Definition: validation.cpp:70
CTxOut out
unspent transaction output
Definition: coins.h:31
uint256 CalcTxInputsHash(const CTransaction &tx)
Definition: specialtx.cpp:155
CDeterministicMNList GetListForBlock(const uint256 &blockHash)
std::string HexStr(const T itbegin, const T itend, bool fSpaces=false)
CScript scriptOperatorPayout
Definition: providertx.h:76
bool HasSelected() const
Definition: coincontrol.h:52
CKeyID keyIDVoting
Definition: providertx.h:31
UniValue protx(const JSONRPCRequest &request)
Definition: rpcevo.cpp:1120
const std::string & get_str() const
Definition: univalue.cpp:307
bool fRequireAllInputs
If false, only include as many inputs as necessary to fulfill a coin selection request. Only usable together with fAllowOtherInputs.
Definition: coincontrol.h:20
UniValue bls_fromsecret(const JSONRPCRequest &request)
Definition: rpcevo.cpp:1202
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:103
std::shared_ptr< const CDeterministicMN > CDeterministicMNCPtr
base58-encoded Dash addresses.
Definition: base58.h:104
void bls_generate_help()
Definition: rpcevo.cpp:1155
CBLSPublicKey pubKeyOperator
Definition: providertx.h:110
UniValue protx_diff(const JSONRPCRequest &request)
Definition: rpcevo.cpp:1073
void ForEachMN(bool onlyValid, Callback &&cb) const
static CKeyID ParsePubKeyIDFromAddress(const std::string &strAddress, const std::string &paramName)
Definition: rpcevo.cpp:131
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:366
const std::string & getValStr() const
Definition: univalue.h:66
bool appendCommand(const std::string &name, const CRPCCommand *pcmd)
Appends a CRPCCommand to the dispatch table.
Definition: server.cpp:350
void MakeNewKey()
Definition: bls.cpp:102
bool DecodeHexTx(CMutableTransaction &tx, const std::string &strHexTx)
Definition: core_read.cpp:91
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:142
UniValue BuildDMNListEntry(CWallet *pwallet, const CDeterministicMNCPtr &dmn, bool detailed)
Definition: rpcevo.cpp:893
bool IsNull() const
Definition: uint256.h:33
bool GetKeyID(CKeyID &keyID) const
Definition: base58.cpp:291
std::string HelpRequiringPassphrase(CWallet *const pwallet)
Definition: rpcwallet.cpp:39
Coin Control Features.
Definition: coincontrol.h:11
Invalid, missing or duplicate parameter.
Definition: protocol.h:52
void AvailableCoins(std::vector< COutput > &vCoins, bool fOnlySafe=true, const CCoinControl *coinControl=NULL, bool fIncludeZeroValue=false, AvailableCoinsType nCoinType=ALL_COINS, bool fUseInstantSend=false) const
populate vCoins with vector of available COutputs.
Definition: wallet.cpp:2496
uint256 ParseHashV(const UniValue &v, std::string strName)
Utilities: convert hex-encoded Values (throws error if not hex).
Definition: server.cpp:141
bool SetString(const char *pszSecret)
Definition: base58.cpp:329
std::string ToString() const
Definition: base58.cpp:193
static bool SignMessage(const std::string &strMessage, std::vector< unsigned char > &vchSigRet, const CKey &key)
Sign the message, returns true if successful.
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:15
std::string GetHelpString(int nParamNum, std::string strParamName)
Definition: rpcevo.cpp:34
#define AssertLockHeld(cs)
Definition: sync.h:88
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:268
bool GetUTXOCoin(const COutPoint &outpoint, Coin &coin)
Definition: validation.cpp:491
#define LOCK2(cs1, cs2)
Definition: sync.h:181
CRPCTable tableRPC
Definition: server.cpp:606
void bls_help()
Definition: rpcevo.cpp:1219
void push_back(const T &value)
Definition: prevector.h:405
void protx_diff_help()
Definition: rpcevo.cpp:1048
static const size_t SerSize
Definition: bls.h:51
static bool CheckWalletOwnsScript(CWallet *pwallet, const CScript &script)
Definition: rpcevo.cpp:875
void protx_help()
Definition: rpcevo.cpp:1094
CScript scriptPubKey
Definition: wallet.h:173
bool push_back(const UniValue &val)
Definition: univalue.cpp:173
UniValue protx_info(const JSONRPCRequest &request)
Definition: rpcevo.cpp:1027
static CBLSPublicKey ParseBLSPubKey(const std::string &hexKey, const std::string &paramName)
Definition: rpcevo.cpp:141
CTransactionRef tx
Definition: wallet.h:214
UniValue params
Definition: server.h:49
std::string ToString() const
Definition: bls.h:210
#define LOCK(cs)
Definition: sync.h:180
const char * name
Definition: rest.cpp:34
A base58-encoded secret key.
Definition: base58.h:126
bool GetKey(const CKeyID &address, CKey &keyOut) const override
GetKey implementation that can derive a HD private key on the fly.
Definition: wallet.cpp:222
void ListProTxCoins(std::vector< COutPoint > &vOutpts)
Definition: wallet.cpp:4544
CService addr
Definition: providertx.h:75
static const uint16_t CURRENT_VERSION
Definition: providertx.h:21
CTxDestination destChange
Definition: coincontrol.h:14
void Select(const COutPoint &output)
Definition: coincontrol.h:62
bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
Parse number as fixed point according to JSON number syntax.
std::string MakeSignString() const
Definition: providertx.cpp:386
uint32_t n
Definition: transaction.h:30
CKeyID keyIDOwner
Definition: providertx.h:29
void RegisterEvoRPCCommands(CRPCTable &tableRPC)
Register Evo RPC commands.
Definition: rpcevo.cpp:1260
uint16_t nVersion
Definition: providertx.h:24
bool empty() const
Definition: univalue.h:67
CDeterministicMNManager * deterministicMNManager
int GetDefaultPort() const
Definition: chainparams.h:62
An output of a transaction.
Definition: transaction.h:144
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:74
std::string ToString() const
Definition: uint256.cpp:62
Invalid address or key.
Definition: protocol.h:50
static CBLSSecretKey ParseBLSSecretKey(const std::string &hexKey, const std::string &paramName)
Definition: rpcevo.cpp:150
CScript GetScriptForDestination(const CTxDestination &dest)
Definition: standard.cpp:260
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: server.cpp:568
CScript scriptPayout
Definition: providertx.h:33
static std::pair< std::string, UniValue > Pair(const char *cKey, const char *cVal)
Definition: univalue.h:166
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:26
std::vector< CTxOut > vout
Definition: transaction.h:317
CScript scriptPayout
Definition: providertx.h:112
void LockCoin(const COutPoint &output)
Definition: wallet.cpp:4498
UniValue bls_generate(const JSONRPCRequest &request)
Definition: rpcevo.cpp:1170
bool SetString(const char *psz, unsigned int nVersionBytes=1)
Definition: base58.cpp:171
A transaction with a bunch of additional info that only the owner cares about.
Definition: wallet.h:291
static const CRPCCommand commands[]
Definition: rpcevo.cpp:1253
uint16_t nOperatorReward
Definition: providertx.h:32
std::vector< uint8_t > vExtraPayload
Definition: transaction.h:319
bool fHelp
Definition: server.h:50
Capture information about block/transaction validation.
Definition: validation.h:22
256-bit opaque blob.
Definition: uint256.h:124
std::string EncodeHexTx(const CTransaction &tx)
Definition: core_write.cpp:117
UniValue _bls(const JSONRPCRequest &request)
Definition: rpcevo.cpp:1233
std::string FormatStateMessage(const CValidationState &state)
Convert CValidationState to a human-readable message for logging.
Definition: validation.cpp:620
bool GetTransaction(const uint256 &hash, CTransactionRef &txOut, const Consensus::Params &consensusParams, uint256 &hashBlock, bool fAllowSlow)
Return transaction in txOut, and if it was found inside a block, its hash is placed in hashBlock...
Definition: validation.cpp:989
bool IsValid() const
Definition: base58.cpp:322
#define ARRAYLEN(array)
bool setArray()
Definition: univalue.cpp:159
A key allocated from the key pool.
Definition: wallet.h:1179
bool CreateTransaction(const std::vector< CRecipient > &vecSend, CWalletTx &wtxNew, CReserveKey &reservekey, CAmount &nFeeRet, int &nChangePosInOut, std::string &strFailReason, const CCoinControl *coinControl=NULL, bool sign=true, AvailableCoinsType nCoinType=ALL_COINS, bool fUseInstantSend=false, int nExtraPayloadSize=0)
Create a new transaction paying the recipients with a set of coins selected by SelectCoins(); Also cr...
Definition: wallet.cpp:3325
const CChainParams & Params()
Return the currently selected parameters.
UniValue sendrawtransaction(const JSONRPCRequest &request)
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:376
void protx_info_help()
Definition: rpcevo.cpp:1012
int GetUTXOConfirmations(const COutPoint &outpoint)
Definition: validation.cpp:508
std::vector< unsigned char > vchSig
Definition: providertx.h:114
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:14
bool Lookup(const char *pszName, std::vector< CService > &vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
Definition: netbase.cpp:155
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:29
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or NULL if none.
Definition: chain.h:450
CBLSPublicKey GetPublicKey() const
Definition: bls.cpp:147
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances...
Definition: wallet.h:672
const UniValue NullUniValue
Definition: univalue.cpp:78
CWallet * GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: rpcwallet.cpp:34
bool ParseBoolV(const UniValue &v, const std::string &strName)
Definition: server.cpp:199
uint16_t nVersion
Definition: providertx.h:73
uint16_t nReason
Definition: providertx.h:156
A mutable version of CTransaction.
Definition: transaction.h:312
static CKey ParsePrivKey(CWallet *pwallet, const std::string &strKeyOrAddress, bool allowAddresses=true)
Definition: rpcevo.cpp:106
UniValue signrawtransaction(const JSONRPCRequest &request)
UniValue JSONRPCError(int code, const std::string &message)
Definition: protocol.cpp:55
size_t size() const
Definition: univalue.h:69
An encapsulated private key.
Definition: key.h:35
uint16_t nVersion
Definition: providertx.h:154
CTxDestination Get() const
Definition: base58.cpp:260
uint16_t nVersion
Definition: providertx.h:107
void SetTxPayload(CMutableTransaction &tx, const T &payload)
Definition: specialtx.h:43
CBLSPublicKey pubKeyOperator
Definition: providertx.h:30
static bool CheckWalletOwnsKey(CWallet *pwallet, const CKeyID &keyID)
Definition: rpcevo.cpp:864
uint256 proTxHash
Definition: providertx.h:155
bool HaveKey(const CKeyID &address) const override
HaveKey implementation that also checks the mapHdPubKeys.
Definition: wallet.cpp:250
bool CheckSpecialTx(const CTransaction &tx, const CBlockIndex *pindexPrev, CValidationState &state)
Definition: specialtx.cpp:20
void EnsureWalletIsUnlocked(CWallet *const pwallet)
Definition: rpcwallet.cpp:57
CBLSSignature Sign(const uint256 &hash) const
Definition: bls.cpp:160
CService addr
Definition: providertx.h:28
std::string ToStringShort() const
Definition: transaction.cpp:17
Released under the MIT license