PIVX Core  5.6.99
P2P Digital Currency
rpcwallet.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin developers
3 // Copyright (c) 2014-2015 The Dash developers
4 // Copyright (c) 2015-2022 The PIVX Core developers
5 // Distributed under the MIT software license, see the accompanying
6 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
7 
8 #include "wallet/rpcwallet.h"
9 
10 #include "addressbook.h"
11 #include "amount.h"
12 #include "coincontrol.h"
13 #include "core_io.h"
14 #include "destination_io.h"
15 #include "httpserver.h"
16 #include "key_io.h"
17 #include "masternode-sync.h"
18 #include "messagesigner.h"
19 #include "net.h"
20 #include "policy/feerate.h"
21 #include "primitives/transaction.h"
22 #include "rpc/server.h"
23 #include "sapling/key_io_sapling.h"
25 #include "shutdown.h"
26 #include "spork.h"
27 #include "timedata.h"
28 #include "utilmoneystr.h"
29 #include "wallet/wallet.h"
30 #include "wallet/walletdb.h"
31 #include "wallet/walletutil.h"
32 
33 #include <stdint.h>
34 #include <univalue.h>
35 
36 
37 static const std::string WALLET_ENDPOINT_BASE = "/wallet/";
38 
40 {
41  if (request.URI.substr(0, WALLET_ENDPOINT_BASE.size()) == WALLET_ENDPOINT_BASE) {
42  // wallet endpoint was used
43  std::string requestedWallet = urlDecode(request.URI.substr(WALLET_ENDPOINT_BASE.size()));
44  for (CWalletRef pwallet : ::vpwallets) {
45  if (pwallet->GetName() == requestedWallet) {
46  return pwallet;
47  }
48  }
49  throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
50  }
51  return ::vpwallets.size() == 1 || (request.fHelp && ::vpwallets.size() > 0) ? ::vpwallets[0] : nullptr;
52 }
53 
54 std::string HelpRequiringPassphrase(CWallet* const pwallet)
55 {
56  return pwallet && pwallet->IsCrypted() ? "\nRequires wallet passphrase to be set with walletpassphrase call." : "";
57 }
58 
59 bool EnsureWalletIsAvailable(CWallet* const pwallet, bool avoidException)
60 {
61  if (pwallet) return true;
62  if (avoidException) return false;
63  if (::vpwallets.empty()) {
64  // Wallet RPC methods are disabled if no wallets are loaded.
65  throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
66  }
68  "Wallet file not specified (must request wallet RPC through /wallet/<filename> uri-path).");
69 }
70 
71 void EnsureWalletIsUnlocked(CWallet* const pwallet, bool fAllowAnonOnly)
72 {
73  if (pwallet->IsLocked() || (!fAllowAnonOnly && pwallet->fWalletUnlockStaking))
74  throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
75 }
76 
77 static void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
78 {
80 
81  int confirms = wtx.GetDepthInMainChain();
82  entry.pushKV("confirmations", confirms);
83  entry.pushKV("bcconfirmations", confirms); // DEPRECATED in 4.3.99
84  if (wtx.IsCoinBase() || wtx.IsCoinStake())
85  entry.pushKV("generated", true);
86  if (confirms > 0) {
87  entry.pushKV("blockhash", wtx.m_confirm.hashBlock.GetHex());
88  entry.pushKV("blockindex", wtx.m_confirm.nIndex);
89  entry.pushKV("blocktime", LookupBlockIndex(wtx.m_confirm.hashBlock)->GetBlockTime());
90  } else {
91  entry.pushKV("trusted", wtx.IsTrusted());
92  }
93  uint256 hash = wtx.GetHash();
94  entry.pushKV("txid", hash.GetHex());
95  UniValue conflicts(UniValue::VARR);
96  for (const uint256& conflict : wtx.GetConflicts())
97  conflicts.push_back(conflict.GetHex());
98  entry.pushKV("walletconflicts", conflicts);
99  entry.pushKV("time", wtx.GetTxTime());
100  entry.pushKV("timereceived", (int64_t)wtx.nTimeReceived);
101  for (const std::pair<std::string, std::string> & item : wtx.mapValue)
102  entry.pushKV(item.first, item.second);
103 }
104 
105 std::string LabelFromValue(const UniValue& value)
106 {
107  std::string label = value.get_str();
108  if (label == "*")
109  throw JSONRPCError(RPC_WALLET_INVALID_LABEL_NAME, "Invalid label name");
110  return label;
111 }
112 
113 static CTxDestination GetNewAddressFromLabel(CWallet* const pwallet, const std::string purpose, const UniValue &params,
115 {
116  LOCK2(cs_main, pwallet->cs_wallet);
117  // Parse the label first so we don't generate a key if there's an error
118  std::string label;
119  if (!params.isNull() && params.size() > 0)
120  label = LabelFromValue(params[0]);
121 
122  auto r = pwallet->getNewAddress(label, purpose, addrType);
123  if(!r)
124  throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, r.getError());
125  return *r.getObjResult();
126 }
127 
129 static UniValue AddressBookDataToJSON(const AddressBook::CAddressBookData& data, const bool verbose)
130 {
132  if (verbose) {
133  ret.pushKV("name", data.name);
134  }
135  ret.pushKV("purpose", data.purpose);
136  return ret;
137 }
138 
140 bool HaveKey(const CWallet* wallet, const CKey& key)
141 {
142  CKey key2;
143  key2.Set(key.begin(), key.end(), !key.IsCompressed());
144  return wallet->HaveKey(key.GetPubKey().GetID()) || wallet->HaveKey(key2.GetPubKey().GetID());
145 }
146 
148 {
149  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
150 
151  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
152  return NullUniValue;
153 
154  const std::string example_address = "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\"";
155 
156  if (request.fHelp || request.params.size() > 1)
157  throw std::runtime_error(
158  "getaddressinfo ( \"address\" )\n"
159  "\nReturn information about the given PIVX address.\n"
160  "Some of the information will only be present if the address is in the active wallet.\n"
161  "Metadata for shield addresses is available only if the wallet is unlocked.\n"
162  "{Result:\n"
163  " \"address\" : \"address\", (string) The PIVX address validated.\n"
164  " \"isshield\" : true|false, (boolean) If the address is shield or transparent.\n"
165  " \"scriptPubKey\" : \"hex\", (string, only if isshield=false) The hex-encoded scriptPubKey generated by the address.\n"
166  " \"ischange\" : true|false, (boolean) If the transparent address was used for change output.\n"
167  " \"ismine\" : true|false, (boolean) If the address is yours.\n"
168  " \"iswatchonly\" : true|false, (boolean) If the address is watchonly.\n"
169  " \"label\" : \"label\" (string) The label associated with the address, \"\" is the default label.\n"
170  " \"timestamp\" : timestamp, (number, optional) The creation time of the key, if available, expressed in the UNIX epoch time.\n"
171  " \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath, if the key is HD and available.\n"
172  " \"hdseedid\" : \"<hash160>\" (string, optional) The Hash160 of the HD seed.\n"
173  " \"hdmasterfingerprint\" : \"<hash160>\" (string, optional) The fingerprint of the master key.\n"
174  " \"labels\" (json object) An array of labels associated with the address. Currently limited to one label but returned\n"
175  " as an array to keep the API stable if multiple labels are enabled in the future.\n"
176  " [\n"
177  " { (json object of label data)\n"
178  " \"name\" : \"labelname\" (string) The label.\n"
179  " \"purpose\" : \"purpose\" (string) The purpose of the associated address (send or receive).\n"
180  " }\n"
181  " ]\n"
182  "}\n"
183 
184  "\nExamples:\n" +
185  HelpExampleCli("getaddressinfo", example_address) + HelpExampleRpc("getaddressinfo", example_address)
186  );
187 
188  LOCK(pwallet->cs_wallet);
189 
190  const std::string& strAdd = request.params[0].get_str();
192  ret.pushKV("address", strAdd);
193 
194  const CWDestination& dest = Standard::DecodeDestination(strAdd);
195  // Make sure the destination is valid
196  if (!Standard::IsValidDestination(dest)) {
197  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
198  }
199 
200  const CTxDestination* pTransDest = Standard::GetTransparentDestination(dest);
201  ret.pushKV("isshield", pTransDest == nullptr);
202 
203  if (pTransDest) {
204  CScript scriptPubKey = GetScriptForDestination(*pTransDest);
205  ret.pushKV("scriptPubKey", HexStr(scriptPubKey));
206  ret.pushKV("ischange", pwallet->IsChange(scriptPubKey));
207  }
208 
209  isminetype mine = IsMine(*pwallet, dest);
210  ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE_ALL));
211  ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY_ALL));
212 
213  // Return label field if existing. Currently only one label can be
214  // associated with an address, so the label should be equivalent to the
215  // value of the name key/value pair in the labels array below.
216  if (pwallet->HasAddressBook(dest)) {
217  ret.pushKV("label", pwallet->GetNameForAddressBookEntry(dest));
218  }
219 
220  ScriptPubKeyMan* spk_man = pwallet->GetScriptPubKeyMan();
221  SaplingScriptPubKeyMan* sspk_man = pwallet->GetSaplingScriptPubKeyMan();
222  CKeyMetadata* meta = nullptr;
223 
224  if (spk_man && pTransDest) {
225  // transparent destination
226  const CKeyID* keyID = boost::get<CKeyID>(pTransDest);
227  if (keyID) {
228  auto it = pwallet->mapKeyMetadata.find(*keyID);
229  if(it != pwallet->mapKeyMetadata.end()) {
230  meta = &it->second;
231  }
232  }
233  } else if (sspk_man && !pTransDest) {
234  // shield destination
237  if (pwallet->GetSaplingExtendedSpendingKey(pa, extsk)) {
238  const auto& ivk = extsk.expsk.full_viewing_key().in_viewing_key();
239  auto it = sspk_man->mapSaplingZKeyMetadata.find(ivk);
240  if (it != sspk_man->mapSaplingZKeyMetadata.end()) {
241  meta = &it->second;
242  }
243  }
244  }
245 
246  // Add metadata
247  if (meta) {
248  ret.pushKV("timestamp", meta->nCreateTime);
249  if (meta->HasKeyOrigin()) {
250  ret.pushKV("hdkeypath", meta->key_origin.pathToString());
251  ret.pushKV("hdseedid", meta->hd_seed_id.GetHex());
252  ret.pushKV("hdmasterfingerprint", HexStr(meta->key_origin.fingerprint));
253  }
254  }
255 
256  // Return a `labels` array containing the label associated with the address,
257  // equivalent to the `label` field above. Currently only one label can be
258  // associated with an address, but we return an array so the API remains
259  // stable if we allow multiple labels to be associated with an address in
260  // the future.
261  //
262  // DEPRECATED: The previous behavior of returning an array containing a JSON
263  // object of `name` and `purpose` key/value pairs has been deprecated.
264  UniValue labels(UniValue::VARR);
265  auto addrBookData = pwallet->GetAddressBookEntry(dest);
266  if (addrBookData) {
267  labels.push_back(AddressBookDataToJSON(*addrBookData, true));
268  }
269  ret.pushKV("labels", std::move(labels));
270 
271  return ret;
272 }
273 
275 {
276  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
277 
278  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
279  return NullUniValue;
280 
281  if (request.fHelp || request.params.size() != 1)
282  throw std::runtime_error(
283  "getaddressesbylabel \"label\"\n"
284  "\nReturns the list of addresses assigned the specified label.\n"
285 
286  "\nArguments:\n"
287  "1. \"label\" (string, required) The label.\n"
288 
289  "\nResult:\n"
290  "{ (json object with addresses as keys)\n"
291  " \"address\": { (json object with information about address)\n"
292  " \"purpose\": \"string\" (string) Purpose of address (\"send\" for sending address, \"receive\" for receiving address)\n"
293  " },...\n"
294  "}\n"
295 
296  "\nExamples:\n"
297  + HelpExampleCli("getaddressesbylabel", "\"tabby\"")
298  + HelpExampleRpc("getaddressesbylabel", "\"tabby\"")
299  );
300 
301  LOCK(pwallet->cs_wallet);
302 
303  std::string label = LabelFromValue(request.params[0]);
304 
305  // Find all addresses that have the given label
307  for (auto it = pwallet->NewAddressBookIterator(); it.IsValid(); it.Next()) {
308  auto addrBook = it.GetValue();
309  if (addrBook.name == label) {
310  if (!addrBook.isShielded()) {
311  ret.pushKV(EncodeDestination(*it.GetCTxDestKey(), AddressBook::IsColdStakingPurpose(addrBook.purpose), AddressBook::IsExchangePurpose(addrBook.purpose)), AddressBookDataToJSON(addrBook, false));
312  } else {
313  ret.pushKV(Standard::EncodeDestination(*it.GetShieldedDestKey()), AddressBookDataToJSON(addrBook, false));
314  }
315  }
316  }
317 
318  if (ret.empty()) {
319  throw JSONRPCError(RPC_WALLET_INVALID_LABEL_NAME, std::string("No addresses with label " + label));
320  }
321 
322  return ret;
323 }
324 
326 {
327  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
328 
329  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
330  return NullUniValue;
331 
332  if (request.fHelp || request.params.size() > 1)
333  throw std::runtime_error(
334  "listlabels ( \"purpose\" )\n"
335  "\nReturns the list of all labels, or labels that are assigned to addresses with a specific purpose.\n"
336 
337  "\nArguments:\n"
338  "1. \"purpose\" (string, optional) Address purpose to list labels for ('send','receive', 'delegable', 'delegator', 'coldstaking', 'coldstaking_send', 'refund'). An empty string is the same as not providing this argument.\n"
339 
340  "\nResult:\n"
341  "[ (json array of string)\n"
342  " \"label\", (string) Label name\n"
343  " ...\n"
344  "]\n"
345 
346  "\nExamples:\n"
347  "\nList all labels\n"
348  + HelpExampleCli("listlabels", "") +
349  "\nList labels that have receiving addresses\n"
350  + HelpExampleCli("listlabels", "receive") +
351  "\nList labels that have sending addresses\n"
352  + HelpExampleCli("listlabels", "send") +
353  "\nAs json rpc call\n"
354  + HelpExampleRpc("listlabels", "receive")
355  );
356 
357  LOCK(pwallet->cs_wallet);
358 
359  std::string purpose;
360  if (!request.params[0].isNull()) {
361  purpose = request.params[0].get_str();
362  }
363 
364  // Add to a set to sort by label name, then insert into Univalue array
365  std::set<std::string> label_set;
366  for (auto it = pwallet->NewAddressBookIterator(); it.IsValid(); it.Next()) {
367  auto addrBook = it.GetValue();
368  if (purpose.empty() || addrBook.purpose == purpose) {
369  label_set.insert(addrBook.name);
370  }
371  }
372 
374  for (const std::string& name : label_set) {
375  ret.push_back(name);
376  }
377 
378  return ret;
379 }
380 
381 CPubKey parseWIFKey(std::string strKey, CWallet* pwallet)
382 {
383  CKey key = KeyIO::DecodeSecret(strKey);
384  if (!key.IsValid()) {
385  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
386  }
387 
388  if (HaveKey(pwallet, key)) {
389  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key (either as an HD seed or as a loose private key)");
390  }
391  return pwallet->GetScriptPubKeyMan()->DeriveNewSeed(key);
392 }
393 
395 {
396  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
397 
398  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
399  return NullUniValue;
400 
401  if (request.fHelp || request.params.size() != 0)
402  throw std::runtime_error("upgradewallet\n"
403  "Bump the wallet features to the latest supported version. Non-HD wallets will be upgraded to HD wallet functionality. "
404  "Marking all the previous keys as pre-split keys and managing them separately. Once the last key in the pre-split keypool gets marked as used (received balance), the wallet will automatically start using the HD generated keys.\n"
405  "The upgraded HD wallet will have a new HD seed set so that new keys added to the keypool will be derived from this new seed.\n"
406  "Wallets that are already running the latest HD version will be upgraded to Sapling support\n"
407  "Enabling the Sapling key manager. Sapling keys will be deterministically derived by the same HD wallet seed.\n"
408  "Wallets that are running the latest Sapling version will not be upgraded"
409  "\nNote that you will need to MAKE A NEW BACKUP of your wallet after upgrade it.\n"
410  + HelpRequiringPassphrase(pwallet) + "\n"
411  + HelpExampleCli("upgradewallet", "") + HelpExampleRpc("upgradewallet", "")
412  );
413 
414  LOCK2(cs_main, pwallet->cs_wallet);
415 
416  // Do not do anything to wallets already upgraded
417  if (pwallet->CanSupportFeature(FEATURE_LATEST)) {
418  throw JSONRPCError(RPC_WALLET_ERROR, "Cannot upgrade the wallet. The wallet is already running the latest version");
419  }
420 
421  EnsureWalletIsUnlocked(pwallet);
422 
423  // Get version
424  int prev_version = pwallet->GetVersion();
425  // Upgrade wallet's version
426  pwallet->SetMinVersion(FEATURE_LATEST);
427  pwallet->SetMaxVersion(FEATURE_LATEST);
428 
429  // Upgrade to HD
430  std::string upgradeError;
431  if (!pwallet->Upgrade(upgradeError, prev_version)) {
432  upgradeError = strprintf("Error: Cannot upgrade wallet, %s", upgradeError);
433  throw JSONRPCError(RPC_WALLET_ERROR, upgradeError);
434  }
435 
436  return NullUniValue;
437 }
438 
440 {
441  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
442 
443  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
444  return NullUniValue;
445 
446  if (request.fHelp || request.params.size() > 2)
447  throw std::runtime_error("sethdseed ( newkeypool \"seed\" )\n"
448  "Set or generate a new HD wallet seed. Non-HD wallets will not be upgraded to being a HD wallet. Wallets that are already\n"
449  "HD will have a new HD seed set so that new keys added to the keypool will be derived from this new seed.\n"
450  "\nNote that you will need to MAKE A NEW BACKUP of your wallet after setting the HD wallet seed.\n"
451  + HelpRequiringPassphrase(pwallet) + "\n"
452 
453  "\nArguments:\n"
454  "1. newkeypool (boolean, optional, default true): Whether to flush old unused addresses, including change addresses, from the keypool and regenerate it.\n"
455  " If true, the next address from getnewaddress and change address from getrawchangeaddress will be from this new seed.\n"
456  " If false, addresses (including change addresses if the wallet already had HD Chain Split enabled) from the existing\n"
457  " keypool will be used until it has been depleted."
458  "2. \"seed\" (string, optional, default random seed): The WIF private key to use as the new HD seed.\n"
459  " The seed value can be retrieved using the dumpwallet command. It is the private key marked hdseed=1"
460  + HelpExampleCli("sethdseed", "")
461  + HelpExampleCli("sethdseed", "false")
462  + HelpExampleCli("sethdseed", "true \"wifkey\"")
463  + HelpExampleRpc("sethdseed", "true, \"wifkey\"")
464  );
465 
466  if (IsInitialBlockDownload()) {
467  throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Cannot set a new HD seed while still in Initial Block Download");
468  }
469 
470  // Make sure the results are valid at least up to the most recent block
471  // the user could have gotten from another RPC command prior to now
473 
474  LOCK2(cs_main, pwallet->cs_wallet);
475 
476  // Do not do anything to non-HD wallets
478  throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set a HD seed on a non-HD wallet. Start with -upgradewallet in order to upgrade a non-HD wallet to HD");
479  }
480 
481  EnsureWalletIsUnlocked(pwallet);
482 
483  bool flush_key_pool = true;
484  if (!request.params[0].isNull()) {
485  flush_key_pool = request.params[0].get_bool();
486  }
487 
488  ScriptPubKeyMan* spk_man = pwallet->GetScriptPubKeyMan();
489  CPubKey master_pub_key = request.params[1].isNull() ?
490  spk_man->GenerateNewSeed() : parseWIFKey(request.params[1].get_str(), pwallet);
491 
492  spk_man->SetHDSeed(master_pub_key, true);
493  if (flush_key_pool) spk_man->NewKeyPool();
494 
495  // Update Sapling chain
497  pwallet->GetSaplingScriptPubKeyMan() : nullptr;
498  if (sspk_man) {
499  sspk_man->SetHDSeed(master_pub_key, true);
500  }
501 
502  return NullUniValue;
503 }
504 
506 {
507  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
508 
509  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
510  return NullUniValue;
511 
512  if (request.fHelp || request.params.size() > 1)
513  throw std::runtime_error(
514  "getnewaddress ( \"label\" )\n"
515  "\nReturns a new PIVX address for receiving payments.\n"
516  "If 'label' is specified, it is added to the address book \n"
517  "so payments received with the address will be associated with 'label'.\n"
518 
519  "\nArguments:\n"
520  "1. \"label\" (string, optional) The label name for the address to be linked to. if not provided, the default label \"\" is used. It can also be set to the empty string \"\" to represent the default label. The label does not need to exist, it will be created if there is no label by the given name.\n"
521 
522  "\nResult:\n"
523  "\"pivxaddress\" (string) The new pivx address\n"
524 
525  "\nExamples:\n" +
526  HelpExampleCli("getnewaddress", "") + HelpExampleRpc("getnewaddress", ""));
527 
528  return EncodeDestination(GetNewAddressFromLabel(pwallet, AddressBook::AddressBookPurpose::RECEIVE, request.params));
529 }
530 
532 {
533  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
534 
535  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
536  return NullUniValue;
537  }
538 
539  if (request.fHelp || request.params.size() > 1)
540  throw std::runtime_error(
541  "getnewexchangeaddress ( \"label\" )\n"
542  "\nReturns a new PIVX exchange address for receiving transparent funds only.\n"
543 
544  "\nArguments:\n"
545  "1. \"label\" (string, optional) The label name for the address to be linked to. if not provided, the default label \"\" is used. It can also be set to the empty string \"\" to represent the default label. The label does not need to exist, it will be created if there is no label by the given name.\n"
546 
547 
548  "\nResult:\n"
549  "\"pivxaddress\" (string) The new pivx exchange address\n"
550 
551  "\nExamples:\n" +
552  HelpExampleCli("getnewexchangeaddress", "") + HelpExampleRpc("getnewexchangeaddress", ""));
553 
554  LOCK2(cs_main, pwallet->cs_wallet);
555 
556  return EncodeDestination(GetNewAddressFromLabel(pwallet, "exchange", request.params, CChainParams::EXCHANGE_ADDRESS), CChainParams::EXCHANGE_ADDRESS);
557 }
558 
560 {
561  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
562 
563  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
564  return NullUniValue;
565 
566  if (request.fHelp || request.params.size() > 1)
567  throw std::runtime_error(
568  "getnewstakingaddress ( \"label\" )\n"
569  "\nReturns a new PIVX cold staking address for receiving delegated cold stakes.\n"
570 
571  "\nArguments:\n"
572  "1. \"label\" (string, optional) The label name for the address to be linked to. if not provided, the default label \"\" is used. It can also be set to the empty string \"\" to represent the default label. The label does not need to exist, it will be created if there is no label by the given name.\n"
573 
574 
575  "\nResult:\n"
576  "\"pivxaddress\" (string) The new pivx address\n"
577 
578  "\nExamples:\n" +
579  HelpExampleCli("getnewstakingaddress", "") + HelpExampleRpc("getnewstakingaddress", ""));
580 
581  return EncodeDestination(GetNewAddressFromLabel(pwallet, "coldstaking", request.params, CChainParams::STAKING_ADDRESS), CChainParams::STAKING_ADDRESS);
582 }
583 
585 {
586  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
587 
588  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
589  return NullUniValue;
590 
591  if (request.fHelp || request.params.size() > 1)
592  throw std::runtime_error(
593  "getnewshieldaddress ( \"label\" )\n"
594  "\nReturns a new shield address for receiving payments.\n"
595  "If 'label' is specified, it is added to the address book \n"
596  "so payments received with the shield address will be associated with 'label'.\n"
597  + HelpRequiringPassphrase(pwallet) + "\n"
598 
599  "\nArguments:\n"
600  "1. \"label\" (string, optional) The label name for the address to be linked to. if not provided, the default label \"\" is used. It can also be set to the empty string \"\" to represent the default label. The label does not need to exist, it will be created if there is no label by the given name.\n"
601 
602  "\nResult:\n"
603  "\"address\" (string) The new shield address.\n"
604 
605  "\nExamples:\n"
606  + HelpExampleCli("getnewshieldaddress", "")
607  + HelpExampleRpc("getnewshieldaddress", "")
608  );
609 
610  std::string label;
611  if (!request.params.empty()) {
612  label = LabelFromValue(request.params[0]);
613  }
614 
615  LOCK2(cs_main, pwallet->cs_wallet);
616 
617  EnsureWalletIsUnlocked(pwallet);
618 
619  return KeyIO::EncodePaymentAddress(pwallet->GenerateNewSaplingZKey(label));
620 }
621 
622 static inline std::string HexStrTrimmed(std::array<unsigned char, ZC_MEMO_SIZE> vch)
623 {
624  return HexStr(std::vector<unsigned char>(vch.begin(), FindFirstNonZero(vch.rbegin(), vch.rend()).base()));
625 }
626 
628 {
629  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
630 
631  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
632  return NullUniValue;
633 
634  if (request.fHelp || request.params.size() > 4)
635  throw std::runtime_error(
636  "listshieldunspent ( minconf maxconf include_watchonly [\"shield_addr\",...] )\n"
637  "\nReturns array of unspent shield notes with between minconf and maxconf (inclusive) confirmations.\n"
638  "Optionally filter to only include notes sent to specified addresses.\n"
639  "When minconf is 0, unspent notes with zero confirmations are returned, even though they are not immediately spendable.\n"
640 
641  "\nArguments:\n"
642  "1. minconf (numeric, optional, default=1) The minimum confirmations to filter\n"
643  "2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter\n"
644  "3. include_watchonly (bool, optional, default=false) Also include watchonly addresses (see 'importsaplingviewingkey')\n"
645  "4. \"addresses\" (string) A json array of shield addrs to filter on. Duplicate addresses not allowed.\n"
646  " [\n"
647  " \"address\" (string) shield addr\n"
648  " ,...\n"
649  " ]\n"
650 
651  "\nResult:\n"
652  "[ (array of json object)\n"
653  " {\n"
654  " \"txid\" : \"txid\", (string) the transaction id \n"
655  " \"outindex\" (sapling) : n, (numeric) the output index\n"
656  " \"confirmations\" : n, (numeric) the number of confirmations\n"
657  " \"spendable\" : true|false, (boolean) true if note can be spent by wallet, false if address is watchonly\n"
658  " \"address\" : \"address\", (string) the shield address\n"
659  " \"amount\": xxxxx, (numeric) the amount of value in the note\n"
660  " \"memo\": xxxxx, (string) hexadecimal string representation of memo field\n"
661  " \"change\": true|false, (boolean) true if the address that received the note is also one of the sending addresses\n"
662  " \"nullifier\": xxxxx, (string) the note's nullifier, hex encoded"
663  " }\n"
664  " ,...\n"
665  "]\n"
666 
667  "\nExamples\n"
668  + HelpExampleCli("listshieldunspent", "")
669  + HelpExampleCli("listshieldunspent", "6 9999999 false \"[\\\"ptestsapling1h0w73csah2aq0a32h42kr7tq4htlt5wfn4ejxfnm56f6ehjvek7k4e244g6v8v3pgylmz5ea8jh\\\",\\\"ptestsapling1h0w73csah2aq0a32h42kr7tq4htlt5wfn4ejxfnm56f6ehjvek7k4e244g6v8v3pgylmz5ea8jh\\\"]\"")
670  + HelpExampleRpc("listshieldunspent", "6 9999999 false \"[\\\"ptestsapling1h0w73csah2aq0a32h42kr7tq4htlt5wfn4ejxfnm56f6ehjvek7k4e244g6v8v3pgylmz5ea8jh\\\",\\\"ptestsapling1h0w73csah2aq0a32h42kr7tq4htlt5wfn4ejxfnm56f6ehjvek7k4e244g6v8v3pgylmz5ea8jh\\\"]\"")
671  );
672 
673  RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM, UniValue::VBOOL, UniValue::VARR});
674 
675  int nMinDepth = request.params.size() > 0 ? request.params[0].get_int() : 1;
676  if (nMinDepth < 0) {
677  throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
678  }
679 
680  int nMaxDepth = request.params.size() > 1 ? request.params[1].get_int() : 9999999;
681  if (nMaxDepth < nMinDepth) {
682  throw JSONRPCError(RPC_INVALID_PARAMETER, "Maximum number of confirmations must be greater or equal to the minimum number of confirmations");
683  }
684 
685  std::set<libzcash::PaymentAddress> shieldAddrs = {};
686  bool fIncludeWatchonly = request.params.size() > 2 && request.params[2].get_bool();
687 
688  LOCK2(cs_main, pwallet->cs_wallet);
689 
690  // User has supplied shield addrs to filter on
691  if (request.params.size() > 3) {
692  UniValue addresses = request.params[3].get_array();
693  if (addresses.size()==0)
694  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, addresses array is empty.");
695 
696  // Keep track of addresses to spot duplicates
697  std::set<std::string> setAddress;
698 
699  // Sources
700  for (const UniValue& o : addresses.getValues()) {
701  if (!o.isStr()) {
702  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected string");
703  }
704  std::string address = o.get_str();
705  auto shieldAddr = KeyIO::DecodePaymentAddress(address);
706  if (!IsValidPaymentAddress(shieldAddr)) {
707  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, address is not a valid shield address: ") + address);
708  }
709  libzcash::SaplingPaymentAddress paymentAddress = *boost::get<libzcash::SaplingPaymentAddress>(&shieldAddr);
710  bool hasSpendingKey = pwallet->HaveSpendingKeyForPaymentAddress(paymentAddress);
711  if (!fIncludeWatchonly && !hasSpendingKey) {
712  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, spending key for address does not belong to wallet: ") + address);
713  }
714  shieldAddrs.insert(shieldAddr);
715 
716  if (setAddress.count(address)) {
717  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + address);
718  }
719  setAddress.insert(address);
720  }
721  } else {
722  // User did not provide shield addrs, so use default i.e. all addresses
723  std::set<libzcash::SaplingPaymentAddress> saplingzaddrs = {};
724  pwallet->GetSaplingPaymentAddresses(saplingzaddrs);
725  shieldAddrs.insert(saplingzaddrs.begin(), saplingzaddrs.end());
726  }
727 
728  UniValue results(UniValue::VARR);
729 
730  if (shieldAddrs.size() > 0) {
731  std::vector<SaplingNoteEntry> saplingEntries;
732  pwallet->GetSaplingScriptPubKeyMan()->GetFilteredNotes(saplingEntries, shieldAddrs, nMinDepth, nMaxDepth, true, !fIncludeWatchonly, false);
733  std::set<std::pair<libzcash::PaymentAddress, uint256>> nullifierSet = pwallet->GetSaplingScriptPubKeyMan()->GetNullifiersForAddresses(shieldAddrs);
734 
735  for (const auto& entry : saplingEntries) {
737  obj.pushKV("txid", entry.op.hash.ToString());
738  obj.pushKV("outindex", (int)entry.op.n);
739  obj.pushKV("confirmations", entry.confirmations);
740  bool hasSaplingSpendingKey = pwallet->HaveSpendingKeyForPaymentAddress(entry.address);
741  obj.pushKV("spendable", hasSaplingSpendingKey);
742  obj.pushKV("address", KeyIO::EncodePaymentAddress(entry.address));
743  obj.pushKV("amount", ValueFromAmount(CAmount(entry.note.value()))); // note.value() is equivalent to plaintext.value()
744  obj.pushKV("memo", HexStrTrimmed(entry.memo));
745  if (hasSaplingSpendingKey) {
746  obj.pushKV("change", pwallet->GetSaplingScriptPubKeyMan()->IsNoteSaplingChange(nullifierSet, entry.address, entry.op));
747  }
748  const auto& nd = pwallet->mapWallet.at(entry.op.hash).mapSaplingNoteData.at(entry.op);
749  if (nd.nullifier) {
750  obj.pushKV("nullifier", nd.nullifier->ToString());
751  }
752  results.push_back(obj);
753  }
754  }
755 
756  return results;
757 }
758 
760 {
761  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
762 
763  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
764  return NullUniValue;
765 
766  if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
767  throw std::runtime_error(
768  "delegatoradd \"address\" ( \"label\" )\n"
769  "\nAdd the provided address <address> into the allowed delegators AddressBook.\n"
770  "This enables the staking of coins delegated to this wallet, owned by <addr>\n"
771 
772  "\nArguments:\n"
773  "1. \"address\" (string, required) The address to whitelist\n"
774  "2. \"label\" (string, optional) A label for the address to whitelist\n"
775 
776  "\nResult:\n"
777  "true|false (boolean) true if successful.\n"
778 
779  "\nExamples:\n" +
780  HelpExampleCli("delegatoradd", "DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6") +
781  HelpExampleRpc("delegatoradd", "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\"") +
782  HelpExampleRpc("delegatoradd", "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\" \"myPaperWallet\""));
783 
784  bool isStaking = false;
785  bool isExchange = false;
786  CTxDestination dest = DecodeDestination(request.params[0].get_str(), isStaking, isExchange);
787  if (!IsValidDestination(dest) || isStaking)
788  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid PIVX address");
789 
790  const std::string strLabel = (request.params.size() > 1 ? request.params[1].get_str() : "");
791 
792  const CKeyID* keyID = boost::get<CKeyID>(&dest);
793  if (!keyID)
794  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to get KeyID from PIVX address");
795 
796  return pwallet->SetAddressBook(*keyID, strLabel, AddressBook::AddressBookPurpose::DELEGATOR);
797 }
798 
800 {
801  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
802 
803  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
804  return NullUniValue;
805 
806  if (request.fHelp || request.params.size() != 1)
807  throw std::runtime_error(
808  "delegatorremove \"address\"\n"
809  "\nUpdates the provided address <address> from the allowed delegators keystore to a \"delegable\" status.\n"
810  "This disables the staking of coins delegated to this wallet, owned by <addr>\n"
811 
812  "\nArguments:\n"
813  "1. \"address\" (string, required) The address to blacklist\n"
814 
815  "\nResult:\n"
816  "true|false (boolean) true if successful.\n"
817 
818  "\nExamples:\n" +
819  HelpExampleCli("delegatorremove", "DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6") +
820  HelpExampleRpc("delegatorremove", "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\""));
821 
822  bool isStaking = false;
823  bool isExchange = false;
824  CTxDestination dest = DecodeDestination(request.params[0].get_str(), isStaking, isExchange);
825  if (!IsValidDestination(dest) || isStaking)
826  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid PIVX address");
827 
828  const CKeyID* keyID = boost::get<CKeyID>(&dest);
829  if (!keyID)
830  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to get KeyID from PIVX address");
831 
832  if (!pwallet->HasAddressBook(*keyID))
833  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to get PIVX address from addressBook");
834 
835  std::string label = "";
836  auto optAdd = pwallet->GetAddressBookEntry(dest);
837  if (optAdd) {
838  label = optAdd->name;
839  }
840 
841  return pwallet->SetAddressBook(*keyID, label, AddressBook::AddressBookPurpose::DELEGABLE);
842 }
843 
844 static UniValue ListaddressesForPurpose(CWallet* const pwallet, const std::string strPurpose)
845 {
846  CChainParams::Base58Type addrType;
847  if (AddressBook::IsColdStakingPurpose(strPurpose)) {
849  } else if (AddressBook::IsExchangePurpose(strPurpose)) {
851  } else {
852  addrType = CChainParams::PUBKEY_ADDRESS;
853  }
855  {
856  LOCK(pwallet->cs_wallet);
857  for (auto it = pwallet->NewAddressBookIterator(); it.IsValid(); it.Next()) {
858  auto addrBook = it.GetValue();
859  if (addrBook.purpose != strPurpose) continue;
860  auto dest = it.GetCTxDestKey();
861  if (!dest) continue;
862  UniValue entry(UniValue::VOBJ);
863  entry.pushKV("label", addrBook.name);
864  entry.pushKV("address", EncodeDestination(*dest, addrType));
865  ret.push_back(entry);
866  }
867  }
868 
869  return ret;
870 }
871 
873 {
874  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
875 
876  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
877  return NullUniValue;
878 
879  if (request.fHelp || request.params.size() > 1)
880  throw std::runtime_error(
881  "listdelegators ( blacklist )\n"
882  "\nShows the list of allowed delegator addresses for cold staking.\n"
883 
884  "\nArguments:\n"
885  "1. blacklist (boolean, optional, default = false) Show addresses removed\n"
886  " from the delegators whitelist\n"
887 
888  "\nResult:\n"
889  "[\n"
890  " {\n"
891  " \"label\": \"yyy\", (string) Address label\n"
892  " \"address\": \"xxx\", (string) PIVX address string\n"
893  " }\n"
894  " ...\n"
895  "]\n"
896 
897  "\nExamples:\n" +
898  HelpExampleCli("listdelegators" , "") +
899  HelpExampleRpc("listdelegators", ""));
900 
901  const bool fBlacklist = (request.params.size() > 0 ? request.params[0].get_bool() : false);
902  return (fBlacklist ?
903  ListaddressesForPurpose(pwallet, AddressBook::AddressBookPurpose::DELEGABLE) :
904  ListaddressesForPurpose(pwallet, AddressBook::AddressBookPurpose::DELEGATOR));
905 }
906 
908 {
909  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
910 
911  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
912  return NullUniValue;
913 
914  if (request.fHelp || !request.params.empty())
915  throw std::runtime_error(
916  "liststakingaddresses\n"
917  "\nShows the list of staking addresses for this wallet.\n"
918 
919  "\nResult:\n"
920  "[\n"
921  " {\n"
922  " \"label\": \"yyy\", (string) Address label\n"
923  " \"address\": \"xxx\", (string) PIVX address string\n"
924  " }\n"
925  " ...\n"
926  "]\n"
927 
928  "\nExamples:\n" +
929  HelpExampleCli("liststakingaddresses" , "") +
930  HelpExampleRpc("liststakingaddresses", ""));
931 
932  return ListaddressesForPurpose(pwallet, AddressBook::AddressBookPurpose::COLD_STAKING);
933 }
934 
936 {
937  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
938 
939  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
940  return NullUniValue;
941 
942  if (request.fHelp || request.params.size() > 1)
943  throw std::runtime_error(
944  "listshieldaddresses ( include_watchonly )\n"
945  "\nReturns the list of shield addresses belonging to the wallet.\n"
946 
947  "\nArguments:\n"
948  "1. include_watchonly (bool, optional, default=false) Also include watchonly addresses (see 'importviewingkey')\n"
949 
950  "\nResult:\n"
951  "[ (json array of string)\n"
952  " \"addr\" (string) a shield address belonging to the wallet\n"
953  " ,...\n"
954  "]\n"
955 
956  "\nExamples:\n"
957  + HelpExampleCli("listshieldaddresses", "")
958  + HelpExampleRpc("listshieldaddresses", "")
959  );
960 
961  LOCK2(cs_main, pwallet->cs_wallet);
962 
963  bool fIncludeWatchonly = false;
964  if (request.params.size() > 0) {
965  fIncludeWatchonly = request.params[0].get_bool();
966  }
967 
969 
970  std::set<libzcash::SaplingPaymentAddress> addresses;
971  pwallet->GetSaplingPaymentAddresses(addresses);
974  for (libzcash::SaplingPaymentAddress addr : addresses) {
975  if (fIncludeWatchonly || pwallet->HaveSpendingKeyForPaymentAddress(addr)) {
977  }
978  }
979  return ret;
980 }
981 
983 {
984  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
985 
986  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
987  return NullUniValue;
988 
989  if (request.fHelp || !request.params.empty())
990  throw std::runtime_error(
991  "getrawchangeaddress\n"
992  "\nReturns a new PIVX address, for receiving change.\n"
993  "This is for use with raw transactions, NOT normal use.\n"
994 
995  "\nResult:\n"
996  "\"address\" (string) The address\n"
997 
998  "\nExamples:\n" +
999  HelpExampleCli("getrawchangeaddress", "") + HelpExampleRpc("getrawchangeaddress", ""));
1000 
1001  LOCK2(cs_main, pwallet->cs_wallet);
1002 
1003  if (!pwallet->IsLocked())
1004  pwallet->TopUpKeyPool();
1005 
1006  CReserveKey reservekey(pwallet);
1007  CPubKey vchPubKey;
1008  if (!reservekey.GetReservedKey(vchPubKey, true))
1009  throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
1010 
1011  reservekey.KeepKey();
1012 
1013  CKeyID keyID = vchPubKey.GetID();
1014 
1015  return EncodeDestination(keyID);
1016 }
1017 
1018 
1020 {
1021  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1022 
1023  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
1024  return NullUniValue;
1025 
1026  if (request.fHelp || request.params.size() != 2)
1027  throw std::runtime_error(
1028  "setlabel \"address\" \"label\"\n"
1029  "\nSets the label associated with the given address.\n"
1030 
1031  "\nArguments:\n"
1032  "1. \"address\" (string, required) The pivx address to be associated with a label.\n"
1033  "2. \"label\" (string, required) The label to assign to the address.\n"
1034 
1035  "\nExamples:\n" +
1036  HelpExampleCli("setlabel", "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\" \"tabby\"") + HelpExampleRpc("setlabel", "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\", \"tabby\""));
1037 
1038  LOCK2(cs_main, pwallet->cs_wallet);
1039 
1040  bool isStaking = false, isExchange = false, isShielded = false;
1041  const CWDestination& dest = Standard::DecodeDestination(request.params[0].get_str(), isStaking, isExchange, isShielded);
1042  // Make sure the destination is valid
1043  if (!Standard::IsValidDestination(dest)) {
1044  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
1045  }
1046 
1047  std::string old_label = pwallet->GetNameForAddressBookEntry(dest);
1048  std::string label = LabelFromValue(request.params[1]);
1049 
1050  pwallet->SetAddressBook(dest, label, "");
1051 
1052  return NullUniValue;
1053 }
1054 
1055 static void SendMoney(CWallet* const pwallet, const CTxDestination& address, CAmount nValue, bool fSubtractFeeFromAmount, CTransactionRef& tx)
1056 {
1057  LOCK2(cs_main, pwallet->cs_wallet);
1058 
1059  // Check amount
1060  if (nValue <= 0)
1061  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid amount");
1062 
1063  if (nValue > pwallet->GetAvailableBalance())
1064  throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds");
1065 
1066  if (!g_connman)
1067  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
1068 
1069  // Parse PIVX address
1070  CScript scriptPubKey = GetScriptForDestination(address);
1071 
1072  // Create and send the transaction
1073  CReserveKey reservekey(pwallet);
1074  CAmount nFeeRequired;
1075  std::string strError;
1076  std::vector<CRecipient> vecSend;
1077  int nChangePosRet = -1;
1078  CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
1079  vecSend.push_back(recipient);
1080  if (!pwallet->CreateTransaction(vecSend, tx, reservekey, nFeeRequired, nChangePosRet, strError)) {
1081  if (!fSubtractFeeFromAmount && nValue + nFeeRequired > pwallet->GetAvailableBalance())
1082  strError = strprintf("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!", FormatMoney(nFeeRequired));
1083  LogPrintf("%s: %s\n", __func__, strError);
1084  throw JSONRPCError(RPC_WALLET_ERROR, strError);
1085  }
1086  const CWallet::CommitResult&& res = pwallet->CommitTransaction(tx, reservekey, g_connman.get());
1087  if (res.status != CWallet::CommitStatus::OK)
1088  throw JSONRPCError(RPC_WALLET_ERROR, res.ToString());
1089 }
1090 
1091 static SaplingOperation CreateShieldedTransaction(CWallet* const pwallet, const JSONRPCRequest& request);
1092 
1093 /*
1094  * redirect sendtoaddress/sendmany inputs to shieldsendmany implementation (CreateShieldedTransaction)
1095  */
1096 static UniValue ShieldSendManyTo(CWallet * const pwallet,
1097  const UniValue& sendTo,
1098  const std::string& commentStr,
1099  const std::string& toStr,
1100  int nMinDepth,
1101  bool fIncludeDelegated,
1102  UniValue subtractFeeFromAmount)
1103 {
1104  // convert params to 'shieldsendmany' format
1105  JSONRPCRequest req;
1107  if (!fIncludeDelegated) {
1108  req.params.push_back(UniValue("from_transparent"));
1109  } else {
1110  req.params.push_back(UniValue("from_trans_cold"));
1111  }
1112  UniValue recipients(UniValue::VARR);
1113  for (const std::string& key : sendTo.getKeys()) {
1114  UniValue recipient(UniValue::VOBJ);
1115  recipient.pushKV("address", key);
1116  recipient.pushKV("amount", sendTo[key]);
1117  recipients.push_back(recipient);
1118  }
1119  req.params.push_back(recipients);
1120  req.params.push_back(nMinDepth);
1121  req.params.push_back(0);
1122  req.params.push_back(subtractFeeFromAmount);
1123 
1124  // send
1125  SaplingOperation operation = CreateShieldedTransaction(pwallet, req);
1126  std::string txid;
1127  auto res = operation.send(txid);
1128  if (!res)
1129  throw JSONRPCError(RPC_WALLET_ERROR, res.getError());
1130 
1131  // add comments
1132  const uint256& txHash = uint256S(txid);
1133  auto it = pwallet->mapWallet.find(txHash);
1134  assert(it != pwallet->mapWallet.end());
1135  if (!commentStr.empty()) {
1136  it->second.mapValue["comment"] = commentStr;
1137  }
1138  if (!toStr.empty()) {
1139  it->second.mapValue["to"] = toStr;
1140  }
1141 
1142  return txid;
1143 }
1144 
1146 {
1147  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1148 
1149  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
1150  return NullUniValue;
1151 
1152  if (request.fHelp || request.params.size() < 2 || request.params.size() > 5)
1153  throw std::runtime_error(
1154  "sendtoaddress \"address\" amount ( \"comment\" \"comment-to\" subtract_fee )\n"
1155  "\nSend an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n" +
1156  HelpRequiringPassphrase(pwallet) + "\n"
1157 
1158  "\nArguments:\n"
1159  "1. \"address\" (string, required) The pivx address to send to.\n"
1160  "2. \"amount\" (numeric, required) The amount in PIV to send. eg 0.1\n"
1161  "3. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
1162  " This is not part of the transaction, just kept in your wallet.\n"
1163  "4. \"comment-to\" (string, optional) A comment to store the name of the person or organization \n"
1164  " to which you're sending the transaction. This is not part of the \n"
1165  " transaction, just kept in your wallet.\n"
1166  "5. subtract_fee (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n"
1167  " The recipient will receive less PIVs than you enter in the amount field.\n"
1168 
1169  "\nResult:\n"
1170  "\"transactionid\" (string) The transaction id.\n"
1171 
1172  "\nExamples:\n" +
1173  HelpExampleCli("sendtoaddress", "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\" 0.1") +
1174  HelpExampleCli("sendtoaddress", "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\" 0.1 \"donation\" \"seans outpost\"") +
1175  HelpExampleCli("sendtoaddress", "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\" 0.1 \"\" \"\" true") +
1176  HelpExampleRpc("sendtoaddress", "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\", 0.1, \"donation\", \"seans outpost\""));
1177 
1178  EnsureWalletIsUnlocked(pwallet);
1179 
1180  // Make sure the results are valid at least up to the most recent block
1181  // the user could have gotten from another RPC command prior to now
1182  pwallet->BlockUntilSyncedToCurrentChain();
1183 
1184  bool isStaking = false, isExchange = false, isShielded = false;
1185  const std::string addrStr = request.params[0].get_str();
1186  const CWDestination& destination = Standard::DecodeDestination(addrStr, isStaking, isExchange, isShielded);
1187  if (!Standard::IsValidDestination(destination) || isStaking)
1188  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid PIVX address");
1189  const std::string commentStr = (request.params.size() > 2 && !request.params[2].isNull()) ?
1190  request.params[2].get_str() : "";
1191  const std::string toStr = (request.params.size() > 3 && !request.params[3].isNull()) ?
1192  request.params[3].get_str() : "";
1193  bool fSubtractFeeFromAmount = request.params.size() > 4 && request.params[4].get_bool();
1194 
1195  if (isShielded) {
1196  UniValue sendTo(UniValue::VOBJ);
1197  sendTo.pushKV(addrStr, request.params[1]);
1198  UniValue subtractFeeFromAmount(UniValue::VARR);
1199  if (fSubtractFeeFromAmount) {
1200  subtractFeeFromAmount.push_back(addrStr);
1201  }
1202  return ShieldSendManyTo(pwallet, sendTo, commentStr, toStr, 1, false, subtractFeeFromAmount);
1203  }
1204 
1205  const CTxDestination& address = *Standard::GetTransparentDestination(destination);
1206 
1207  // Amount
1208  CAmount nAmount = AmountFromValue(request.params[1]);
1209 
1210  CTransactionRef tx;
1211  SendMoney(pwallet, address, nAmount, fSubtractFeeFromAmount, tx);
1212 
1213  // Wallet comments
1214  CWalletTx& wtx = pwallet->mapWallet.at(tx->GetHash());
1215  if (!commentStr.empty())
1216  wtx.mapValue["comment"] = commentStr;
1217  if (!toStr.empty())
1218  wtx.mapValue["to"] = toStr;
1219 
1220  return wtx.GetHash().GetHex();
1221 }
1222 
1223 static UniValue CreateColdStakeDelegation(CWallet* const pwallet, const UniValue& params, CTransactionRef& txNew, CReserveKey& reservekey)
1224 {
1225  LOCK2(cs_main, pwallet->cs_wallet);
1226 
1227  // Check that Cold Staking has been enforced or fForceNotEnabled = true
1228  bool fForceNotEnabled = false;
1229  if (params.size() > 6 && !params[6].isNull())
1230  fForceNotEnabled = params[6].get_bool();
1231 
1232  if (sporkManager.IsSporkActive(SPORK_19_COLDSTAKING_MAINTENANCE) && !fForceNotEnabled) {
1233  std::string errMsg = "Cold Staking temporarily disabled with SPORK 19.\n"
1234  "You may force the stake delegation setting fForceNotEnabled to true.\n"
1235  "WARNING: If relayed before activation, this tx will be rejected resulting in a ban.\n";
1236  throw JSONRPCError(RPC_WALLET_ERROR, errMsg);
1237  }
1238 
1239  // Get Staking Address
1240  bool isStaking{false};
1241  CTxDestination stakeAddr = DecodeDestination(params[0].get_str());
1242  if (!IsValidDestination(stakeAddr) || isStaking)
1243  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid PIVX staking address");
1244 
1245  CKeyID* stakeKey = boost::get<CKeyID>(&stakeAddr);
1246  if (!stakeKey)
1247  throw JSONRPCError(RPC_WALLET_ERROR, "Unable to get stake pubkey hash from stakingaddress");
1248 
1249  // Get Amount
1250  CAmount nValue = AmountFromValue(params[1]);
1251  if (nValue < MIN_COLDSTAKING_AMOUNT)
1252  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid amount (%d). Min amount: %d",
1253  nValue, MIN_COLDSTAKING_AMOUNT));
1254 
1255  // include already delegated coins
1256  bool fUseDelegated = false;
1257  if (params.size() > 4 && !params[4].isNull())
1258  fUseDelegated = params[4].get_bool();
1259 
1260  // Check amount
1261  CAmount currBalance = pwallet->GetAvailableBalance() + (fUseDelegated ? pwallet->GetDelegatedBalance() : 0);
1262  if (nValue > currBalance)
1263  throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds");
1264 
1265  std::string strError;
1266 
1267  // Get Owner Address
1268  std::string ownerAddressStr;
1269  CKeyID ownerKey;
1270  bool isStakingAddress = false;
1271  bool isExchange = false;
1272  if (params.size() > 2 && !params[2].isNull() && !params[2].get_str().empty()) {
1273  // Address provided
1274  CTxDestination dest = DecodeDestination(params[2].get_str(), isStakingAddress, isExchange);
1275  if (!IsValidDestination(dest) || isStakingAddress)
1276  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid PIVX spending address");
1277  ownerKey = *boost::get<CKeyID>(&dest);
1278  // Check that the owner address belongs to this wallet, or fForceExternalAddr is true
1279  bool fForceExternalAddr = params.size() > 3 && !params[3].isNull() ? params[3].get_bool() : false;
1280  if (!fForceExternalAddr && !pwallet->HaveKey(ownerKey)) {
1281  std::string errMsg = strprintf("The provided owneraddress \"%s\" is not present in this wallet.\n", params[2].get_str());
1282  errMsg += "Set 'fExternalOwner' argument to true, in order to force the stake delegation to an external owner address.\n"
1283  "e.g. delegatestake stakingaddress amount owneraddress true.\n"
1284  "WARNING: Only the owner of the key to owneraddress will be allowed to spend these coins after the delegation.";
1286  }
1287  ownerAddressStr = params[2].get_str();
1288  } else {
1289  // Get new owner address from keypool
1290  CTxDestination ownerAddr = GetNewAddressFromLabel(pwallet, "delegated", NullUniValue);
1291  CKeyID* pOwnerKey = boost::get<CKeyID>(&ownerAddr);
1292  assert(pOwnerKey);
1293  ownerKey = *pOwnerKey;
1294  ownerAddressStr = EncodeDestination(ownerAddr);
1295  }
1296 
1297  // Use new opcode after v6.0 enforcement (!TODO: remove after enforcement)
1299 
1300  // Create the transaction
1301  const bool fUseShielded = (params.size() > 5) && params[5].get_bool();
1302  if (!fUseShielded) {
1303  // Delegate transparent coins
1304  CAmount nFeeRequired;
1305  CScript scriptPubKey = fV6Enforced ? GetScriptForStakeDelegation(*stakeKey, ownerKey)
1307  if (!pwallet->CreateTransaction(scriptPubKey, nValue, txNew, reservekey, nFeeRequired, strError, nullptr, (CAmount)0, fUseDelegated)) {
1308  if (nValue + nFeeRequired > currBalance)
1309  strError = strprintf("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!", FormatMoney(nFeeRequired));
1310  LogPrintf("%s : %s\n", __func__, strError);
1311  throw JSONRPCError(RPC_WALLET_ERROR, strError);
1312  }
1313  } else {
1314  // Delegate shield coins
1315  const Consensus::Params& consensus = Params().GetConsensus();
1316  // Check network status
1318  throw JSONRPCError(RPC_INVALID_PARAMETER, "SHIELD in maintenance (SPORK 20)");
1319  }
1320  std::vector<SendManyRecipient> recipients = {SendManyRecipient(ownerKey, *stakeKey, nValue, fV6Enforced)};
1321  SaplingOperation operation(consensus, pwallet);
1322  OperationResult res = operation.setSelectShieldedCoins(true)
1323  ->setRecipients(recipients)
1324  ->build();
1325  if (!res) throw JSONRPCError(RPC_WALLET_ERROR, res.getError());
1326  txNew = MakeTransactionRef(operation.getFinalTx());
1327  }
1328 
1329  UniValue result(UniValue::VOBJ);
1330  result.pushKV("owner_address", ownerAddressStr);
1331  result.pushKV("staker_address", EncodeDestination(stakeAddr, true, false));
1332  return result;
1333 }
1334 
1336 {
1337  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1338 
1339  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
1340  return NullUniValue;
1341 
1342  if (request.fHelp || request.params.size() < 2 || request.params.size() > 7)
1343  throw std::runtime_error(
1344  "delegatestake \"staking_addr\" amount ( \"owner_addr\" ext_owner include_delegated from_shield force )\n"
1345  "\nDelegate an amount to a given address for cold staking. The amount is a real and is rounded to the nearest 0.00000001\n" +
1346  HelpRequiringPassphrase(pwallet) + "\n"
1347 
1348  "\nArguments:\n"
1349  "1. \"staking_addr\" (string, required) The pivx staking address to delegate.\n"
1350  "2. \"amount\" (numeric, required) The amount in PIV to delegate for staking. eg 100\n"
1351  "3. \"owner_addr\" (string, optional) The pivx address corresponding to the key that will be able to spend the stake.\n"
1352  " If not provided, or empty string, a new wallet address is generated.\n"
1353  "4. \"ext_owner\" (boolean, optional, default = false) use the provided 'owneraddress' anyway, even if not present in this wallet.\n"
1354  " WARNING: The owner of the keys to 'owneraddress' will be the only one allowed to spend these coins.\n"
1355  "5. \"include_delegated\" (boolean, optional, default = false) include already delegated inputs if needed.\n"
1356  "6. \"from_shield\" (boolean, optional, default = false) delegate shield funds.\n"
1357  "7. \"force\" (boolean, optional, default = false) ONLY FOR TESTING: force the creation even if SPORK 17 is disabled.\n"
1358 
1359  "\nResult:\n"
1360  "{\n"
1361  " \"owner_address\": \"xxx\" (string) The owner (delegator) owneraddress.\n"
1362  " \"staker_address\": \"xxx\" (string) The cold staker (delegate) stakingaddress.\n"
1363  " \"txid\": \"xxx\" (string) The stake delegation transaction id.\n"
1364  "}\n"
1365 
1366  "\nExamples:\n" +
1367  HelpExampleCli("delegatestake", "\"S1t2a3kab9c8c71VA78xxxy4MxZg6vgeS6\" 100") +
1368  HelpExampleCli("delegatestake", "\"S1t2a3kab9c8c71VA78xxxy4MxZg6vgeS6\" 1000 \"DMJRSsuU9zfyrvxVaAEFQqK4MxZg34fk\"") +
1369  HelpExampleRpc("delegatestake", "\"S1t2a3kab9c8c71VA78xxxy4MxZg6vgeS6\", 1000, \"DMJRSsuU9zfyrvxVaAEFQqK4MxZg34fk\""));
1370 
1371  EnsureWalletIsUnlocked(pwallet);
1372 
1373  // Make sure the results are valid at least up to the most recent block
1374  // the user could have gotten from another RPC command prior to now
1375  pwallet->BlockUntilSyncedToCurrentChain();
1376 
1377  LOCK2(cs_main, pwallet->cs_wallet);
1378 
1379  CTransactionRef wtx;
1380  CReserveKey reservekey(pwallet);
1381  UniValue ret = CreateColdStakeDelegation(pwallet, request.params, wtx, reservekey);
1382 
1383  const CWallet::CommitResult& res = pwallet->CommitTransaction(wtx, reservekey, g_connman.get());
1384  if (res.status != CWallet::CommitStatus::OK)
1385  throw JSONRPCError(RPC_WALLET_ERROR, res.ToString());
1386 
1387  ret.pushKV("txid", wtx->GetHash().GetHex());
1388  return ret;
1389 }
1390 
1392 {
1393  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1394 
1395  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
1396  return NullUniValue;
1397 
1398  if (request.fHelp || request.params.size() < 2 || request.params.size() > 7)
1399  throw std::runtime_error(
1400  "rawdelegatestake \"staking_addr\" amount ( \"owner_addr\" ext_owner include_delegated from_shield )\n"
1401  "\nDelegate an amount to a given address for cold staking. The amount is a real and is rounded to the nearest 0.00000001\n"
1402  "\nDelegate transaction is returned as json object." +
1403  HelpRequiringPassphrase(pwallet) + "\n"
1404 
1405  "\nArguments:\n"
1406  "1. \"staking_addr\" (string, required) The pivx staking address to delegate.\n"
1407  "2. \"amount\" (numeric, required) The amount in PIV to delegate for staking. eg 100\n"
1408  "3. \"owner_addr\" (string, optional) The pivx address corresponding to the key that will be able to spend the stake.\n"
1409  " If not provided, or empty string, a new wallet address is generated.\n"
1410  "4. \"ext_owner\" (boolean, optional, default = false) use the provided 'owneraddress' anyway, even if not present in this wallet.\n"
1411  " WARNING: The owner of the keys to 'owneraddress' will be the only one allowed to spend these coins.\n"
1412  "5. \"include_delegated\" (boolean, optional, default = false) include already delegated inputs if needed.\n"
1413  "6. \"from_shield\" (boolean, optional, default = false) delegate shield funds.\n"
1414  "7. \"force\" (boolean, optional, default = false) ONLY FOR TESTING: force the creation even if SPORK 17 is disabled (for tests).\n"
1415 
1416  "\nResult:\n"
1417  "\"transaction\" (string) hex string of the transaction\n"
1418 
1419  "\nExamples:\n" +
1420  HelpExampleCli("rawdelegatestake", "\"S1t2a3kab9c8c71VA78xxxy4MxZg6vgeS6\" 100") +
1421  HelpExampleCli("rawdelegatestake", "\"S1t2a3kab9c8c71VA78xxxy4MxZg6vgeS6\" 1000 \"DMJRSsuU9zfyrvxVaAEFQqK4MxZg34fk\"") +
1422  HelpExampleRpc("rawdelegatestake", "\"S1t2a3kab9c8c71VA78xxxy4MxZg6vgeS6\", 1000, \"DMJRSsuU9zfyrvxVaAEFQqK4MxZg34fk\""));
1423 
1424  EnsureWalletIsUnlocked(pwallet);
1425 
1426  // Make sure the results are valid at least up to the most recent block
1427  // the user could have gotten from another RPC command prior to now
1428  pwallet->BlockUntilSyncedToCurrentChain();
1429 
1430  LOCK2(cs_main, pwallet->cs_wallet);
1431 
1432  CTransactionRef wtx;
1433  CReserveKey reservekey(pwallet);
1434  CreateColdStakeDelegation(pwallet, request.params, wtx, reservekey);
1435 
1436  return EncodeHexTx(*wtx);
1437 }
1438 
1439 
1440 static CAmount getBalanceShieldedAddr(CWallet* const pwallet, Optional<libzcash::SaplingPaymentAddress>& filterAddress, int minDepth = 1, bool ignoreUnspendable=true) {
1441  CAmount balance = 0;
1442  std::vector<SaplingNoteEntry> saplingEntries;
1443  LOCK2(cs_main, pwallet->cs_wallet);
1444  pwallet->GetSaplingScriptPubKeyMan()->GetFilteredNotes(saplingEntries, filterAddress, minDepth, true, ignoreUnspendable);
1445  for (auto & entry : saplingEntries) {
1446  balance += CAmount(entry.note.value());
1447  }
1448  return balance;
1449 }
1450 
1452 {
1453  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1454 
1455  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
1456  return NullUniValue;
1457 
1458  if (request.fHelp || request.params.size() > 3)
1459  throw std::runtime_error(
1460  "getshieldbalance \"address\" ( minconf include_watchonly )\n"
1461  "\nReturn the total shield value of funds stored in the node's wallet or if an address was given,"
1462  "\nreturns the balance of the shield addr belonging to the node's wallet.\n"
1463  "\nCAUTION: If the wallet contains any addresses for which it only has incoming viewing keys,"
1464  "\nthe returned private balance may be larger than the actual balance, because spends cannot"
1465  "\nbe detected with incoming viewing keys.\n"
1466 
1467  "\nArguments:\n"
1468  "1. \"address\" (string, optional) The selected address. If non empty nor \"*\", it must be a Sapling address\n"
1469  "2. minconf (numeric, optional, default=1) Only include private and transparent transactions confirmed at least this many times.\n"
1470  "3. include_watchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress' and 'importsaplingviewingkey')\n"
1471 
1472  "\nResult:\n"
1473  "amount (numeric) the total balance of shield funds (in Sapling addresses)\n"
1474 
1475  "\nExamples:\n"
1476  "\nThe total amount in the wallet\n"
1477  + HelpExampleCli("getshieldbalance", "")
1478  + HelpExampleCli("getshieldbalance", "ptestsapling1h0w73csah2aq0a32h42kr7tq4htlt5wfn4ejxfnm56f6ehjvek7k4e244g6v8v3pgylmz5ea8jh") +
1479  "\nThe total amount in the wallet at least 5 blocks confirmed\n"
1480  + HelpExampleCli("getshieldbalance", "\"*\" \"5\"") +
1481  "\nAs a json rpc call\n"
1482  + HelpExampleRpc("getshieldbalance", "\"*\" \"5\"")
1483  );
1484 
1485  LOCK2(cs_main, pwallet->cs_wallet);
1486 
1488  if (request.params.size() > 0) {
1489  std::string addressStr = request.params[0].get_str();
1490  if (addressStr.empty() || addressStr != "*") {
1491  address = KeyIO::DecodeSaplingPaymentAddress(addressStr);
1492  if (!address) {
1493  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid shield address");
1494  }
1495  }
1496  }
1497 
1498  const int nMinDepth = request.params.size() > 1 ? request.params[1].get_int() : 1;
1499  if (nMinDepth < 0) {
1500  throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
1501  }
1502 
1503  const bool fIncludeWatchonly = request.params.size() > 2 && request.params[2].get_bool();
1504  CAmount nBalance = getBalanceShieldedAddr(pwallet, address, nMinDepth, !fIncludeWatchonly);
1505  return ValueFromAmount(nBalance);
1506 }
1507 
1509 {
1510  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1511 
1512  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
1513  return NullUniValue;
1514 
1515  if (request.fHelp || request.params.size() != 1)
1516  throw std::runtime_error(
1517  "viewshieldtransaction \"txid\"\n"
1518  "\nGet detailed shield information about in-wallet transaction \"txid\"\n"
1519  + HelpRequiringPassphrase(pwallet) + "\n"
1520 
1521  "\nArguments:\n"
1522  "1. \"txid\" (string, required) The transaction id\n"
1523  "\nResult:\n"
1524  "{\n"
1525  " \"txid\" : \"transactionid\", (string) The transaction id\n"
1526  " \"fee\" : x.xxx, (numeric) The transaction fee in " + CURRENCY_UNIT + "\n"
1527  " \"spends\" : [\n"
1528  " {\n"
1529  " \"spend\" : n, (numeric, sapling) the index of the spend within vShieldedSpend\n"
1530  " \"txidPrev\" : \"transactionid\", (string) The id for the transaction this note was created in\n"
1531  " \"outputPrev\" : n, (numeric, sapling) the index of the output within the vShieldedOutput\n"
1532  " \"address\" : \"pivxaddress\", (string) The PIVX address involved in the transaction\n"
1533  " \"value\" : x.xxx (numeric) The amount in " + CURRENCY_UNIT + "\n"
1534  " \"valueSat\" : xxxx (numeric) The amount in satoshis\n"
1535  " }\n"
1536  " ,...\n"
1537  " ],\n"
1538  " \"outputs\" : [\n"
1539  " {\n"
1540  " \"output\" : n, (numeric, sapling) the index of the output within the vShieldedOutput\n"
1541  " \"address\" : \"pivxaddress\", (string) The PIVX address involved in the transaction\n"
1542  " \"outgoing\" : true|false (boolean, sapling) True if the output is not for an address in the wallet\n"
1543  " \"value\" : x.xxx (numeric) The amount in " + CURRENCY_UNIT + "\n"
1544  " \"valueSat\" : xxxx (numeric) The amount in satoshis\n"
1545  " \"memo\" : \"hexmemo\", (string) Hexadecimal string representation of the memo field\n"
1546  " \"memoStr\" : \"memo\", (string) Only returned if memo contains valid UTF-8 text.\n"
1547  " }\n"
1548  " ,...\n"
1549  " ],\n"
1550  "}\n"
1551 
1552  "\nExamples:\n"
1553  + HelpExampleCli("viewshieldtransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1554  + HelpExampleRpc("viewshieldtransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1555  );
1556 
1557  if (!pwallet->HasSaplingSPKM()) {
1558  throw JSONRPCError(RPC_WALLET_ERROR, "Sapling wallet not initialized.");
1559  }
1560 
1561  EnsureWalletIsUnlocked(pwallet);
1562 
1563  // Make sure the results are valid at least up to the most recent block
1564  // the user could have gotten from another RPC command prior to now
1565  pwallet->BlockUntilSyncedToCurrentChain();
1566 
1567  LOCK2(cs_main, pwallet->cs_wallet);
1568 
1569  uint256 hash(ParseHashV(request.params[0], "txid"));
1570 
1571  UniValue entry(UniValue::VOBJ);
1572  auto it = pwallet->mapWallet.find(hash);
1573  if (it == pwallet->mapWallet.end())
1574  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
1575  const CWalletTx& wtx = it->second;
1576 
1577  if (!wtx.tx->IsShieldedTx()) {
1578  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid transaction, no shield data available");
1579  }
1580 
1581  entry.pushKV("txid", hash.GetHex());
1582 
1583  UniValue spends(UniValue::VARR);
1584  UniValue outputs(UniValue::VARR);
1585 
1586  auto addMemo = [](UniValue& entry, const Optional<std::array<unsigned char, ZC_MEMO_SIZE>>& optMemo) {
1587  // empty memo
1588  if (!static_cast<bool>(optMemo)) {
1589  const std::array<unsigned char, 1> memo {0xF6};
1590  entry.pushKV("memo", HexStr(memo));
1591  return;
1592  }
1593  const auto& memo = *optMemo;
1594  auto end = FindFirstNonZero(memo.rbegin(), memo.rend());
1595  entry.pushKV("memo", HexStr(std::vector<unsigned char>(memo.begin(), end.base())));
1596  // If the leading byte is 0xF4 or lower, the memo field should be interpreted as a
1597  // UTF-8-encoded text string.
1598  if (memo[0] <= 0xf4) {
1599  std::string memoStr(memo.begin(), end.base());
1600  if (IsValidUTF8(memoStr)) {
1601  entry.pushKV("memoStr", memoStr);
1602  }
1603  }
1604  };
1605 
1606  auto sspkm = pwallet->GetSaplingScriptPubKeyMan();
1607 
1608  // Collect OutgoingViewingKeys for recovering output information
1609  std::set<uint256> ovks;
1610  // Get the common OVK for recovering t->shield outputs.
1611  // If not already databased, a new one will be generated from the HD seed.
1612  // It is safe to do it here, as the wallet is unlocked.
1613  ovks.insert(sspkm->getCommonOVK());
1614 
1615  // Sapling spends
1616  for (size_t i = 0; i < wtx.tx->sapData->vShieldedSpend.size(); ++i) {
1617  const auto& spend = wtx.tx->sapData->vShieldedSpend[i];
1618 
1619  // Fetch the note that is being spent
1620  auto res = sspkm->mapSaplingNullifiersToNotes.find(spend.nullifier);
1621  if (res == sspkm->mapSaplingNullifiersToNotes.end()) {
1622  continue;
1623  }
1624  const auto& op = res->second;
1625  std::string addrStr = "unknown";
1626  UniValue amountStr = UniValue("unknown");
1627  CAmount amount = 0;
1628  auto wtxPrevIt = pwallet->mapWallet.find(op.hash);
1629  if (wtxPrevIt != pwallet->mapWallet.end()) {
1630  const auto ndIt = wtxPrevIt->second.mapSaplingNoteData.find(op);
1631  if (ndIt != wtxPrevIt->second.mapSaplingNoteData.end()) {
1632  // get cached address and amount
1633  if (ndIt->second.address) {
1634  addrStr = KeyIO::EncodePaymentAddress(*(ndIt->second.address));
1635  }
1636  if (ndIt->second.amount) {
1637  amount = *(ndIt->second.amount);
1638  amountStr = ValueFromAmount(amount);
1639  }
1640  }
1641  }
1642 
1643  UniValue entry_(UniValue::VOBJ);
1644  entry_.pushKV("spend", (int)i);
1645  entry_.pushKV("txidPrev", op.hash.GetHex());
1646  entry_.pushKV("outputPrev", (int)op.n);
1647  entry_.pushKV("address", addrStr);
1648  entry_.pushKV("value", amountStr);
1649  entry_.pushKV("valueSat", amount);
1650  spends.push_back(entry_);
1651  }
1652 
1653  // Sapling outputs
1654  for (uint32_t i = 0; i < wtx.tx->sapData->vShieldedOutput.size(); ++i) {
1655  auto op = SaplingOutPoint(hash, i);
1656  auto it = wtx.mapSaplingNoteData.find(op);
1657  if (it == wtx.mapSaplingNoteData.end()) continue;
1658  const auto& nd = it->second;
1659 
1660  const bool isOutgoing = !nd.IsMyNote();
1661  std::string addrStr = "unknown";
1662  UniValue amountStr = UniValue("unknown");
1663  CAmount amount = 0;
1664  if (nd.address) {
1665  addrStr = KeyIO::EncodePaymentAddress(*(nd.address));
1666  }
1667  if (nd.amount) {
1668  amount = *(nd.amount);
1669  amountStr = ValueFromAmount(amount);
1670  }
1671 
1672  UniValue entry_(UniValue::VOBJ);
1673  entry_.pushKV("output", (int)op.n);
1674  entry_.pushKV("outgoing", isOutgoing);
1675  entry_.pushKV("address", addrStr);
1676  entry_.pushKV("value", amountStr);
1677  entry_.pushKV("valueSat", amount);
1678  addMemo(entry_, nd.memo);
1679 
1680  outputs.push_back(entry_);
1681  }
1682 
1683  entry.pushKV("fee", FormatMoney(pcoinsTip->GetValueIn(*wtx.tx) - wtx.tx->GetValueOut()));
1684  entry.pushKV("spends", spends);
1685  entry.pushKV("outputs", outputs);
1686 
1687  return entry;
1688 }
1689 
1690 static SaplingOperation CreateShieldedTransaction(CWallet* const pwallet, const JSONRPCRequest& request)
1691 {
1692  LOCK2(cs_main, pwallet->cs_wallet);
1693  SaplingOperation operation(Params().GetConsensus(), pwallet);
1694 
1695  // Param 0: source of funds. Can either be a valid address, sapling address,
1696  // or the string "from_transparent"|"from_trans_cold"|"from_shield"
1697  bool fromSapling = false;
1698  std::string sendFromStr = request.params[0].get_str();
1699  if (sendFromStr == "from_transparent") {
1700  // send from any transparent address
1701  operation.setSelectTransparentCoins(true);
1702  } else if (sendFromStr == "from_trans_cold") {
1703  // send from any transparent address + delegations
1704  operation.setSelectTransparentCoins(true, true);
1705  } else if (sendFromStr == "from_shield") {
1706  // send from any shield address
1707  operation.setSelectShieldedCoins(true);
1708  fromSapling = true;
1709  } else {
1710  CTxDestination fromTAddressDest = DecodeDestination(sendFromStr);
1711  if (!IsValidDestination(fromTAddressDest)) {
1712  auto res = KeyIO::DecodePaymentAddress(sendFromStr);
1713  if (!IsValidPaymentAddress(res)) {
1714  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or shield addr.");
1715  }
1716  libzcash::SaplingPaymentAddress fromShieldedAddress = *boost::get<libzcash::SaplingPaymentAddress>(&res);
1717  if (!pwallet->HaveSpendingKeyForPaymentAddress(fromShieldedAddress)) {
1718  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, shield addr spending key not found.");
1719  }
1720  // send from user-supplied shield address
1721  operation.setFromAddress(fromShieldedAddress);
1722  fromSapling = true;
1723  } else {
1724  // send from user-supplied transparent address
1725  operation.setFromAddress(fromTAddressDest);
1726  }
1727  }
1728 
1729  // Param 4: subtractFeeFromAmount addresses
1730  const UniValue subtractFeeFromAmount = request.params[4];
1731 
1732  // Param 1: array of outputs
1733  UniValue outputs = request.params[1].get_array();
1734  if (outputs.empty())
1735  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, amounts array is empty.");
1736 
1737  // Keep track of addresses to spot duplicates
1738  std::set<std::string> setAddress;
1739  // Recipients
1740  std::vector<SendManyRecipient> recipients;
1741  CAmount nTotalOut = 0;
1742  bool containsSaplingOutput = false;
1743 
1744  for (const UniValue& o : outputs.getValues()) {
1745  if (!o.isObject())
1746  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
1747 
1748  // sanity check, report error if unknown key-value pairs
1749  for (const std::string& name_ : o.getKeys()) {
1750  if (name_ != "address" && name_ != "amount" && name_!="memo")
1751  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, unknown key: ")+name_);
1752  }
1753 
1754  std::string address = find_value(o, "address").get_str();
1755  CTxDestination taddr = DecodeDestination(address);
1757 
1758  if (!IsValidDestination(taddr)) {
1759  const auto& addr = KeyIO::DecodePaymentAddress(address);
1760  if (IsValidPaymentAddress(addr)) {
1761  saddr = *(boost::get<libzcash::SaplingPaymentAddress>(&addr));
1762  containsSaplingOutput = true;
1763  } else {
1764  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, unknown address format: ")+address );
1765  }
1766  }
1767 
1768  if (setAddress.count(address))
1769  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ")+address);
1770  setAddress.insert(address);
1771 
1772  UniValue memoValue = find_value(o, "memo");
1773  std::string memo;
1774  if (!memoValue.isNull()) {
1775  memo = memoValue.get_str();
1776  if (!saddr) {
1777  throw JSONRPCError(RPC_INVALID_PARAMETER, "Memo cannot be used with a taddr. It can only be used with a shield addr.");
1778  }
1779  if (memo.length() > ZC_MEMO_SIZE*2) {
1780  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, size of memo is larger than maximum allowed %d", ZC_MEMO_SIZE ));
1781  }
1782  }
1783 
1784  UniValue av = find_value(o, "amount");
1785  CAmount nAmount = AmountFromValue(av);
1786  if (nAmount < 0)
1787  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, amount must be positive");
1788 
1789  bool fSubtractFeeFromAmount = false;
1790  for (unsigned int idx = 0; idx < subtractFeeFromAmount.size(); idx++) {
1791  const UniValue& addr = subtractFeeFromAmount[idx];
1792  if (addr.get_str() == address) {
1793  fSubtractFeeFromAmount = true;
1794  break;
1795  }
1796  }
1797 
1798  if (saddr) {
1799  recipients.emplace_back(*saddr, nAmount, memo, fSubtractFeeFromAmount);
1800  } else {
1801  recipients.emplace_back(taddr, nAmount, fSubtractFeeFromAmount);
1802  }
1803 
1804  nTotalOut += nAmount;
1805  }
1806 
1807  // Check network status
1809  // If Sapling is disabled, do not allow sending from or sending to Sapling addresses.
1810  if (fromSapling || containsSaplingOutput) {
1811  throw JSONRPCError(RPC_INVALID_PARAMETER, "SHIELD in maintenance (SPORK 20)");
1812  }
1813  }
1814 
1815  // Now check the transaction
1816  auto opResult = CheckTransactionSize(recipients, !fromSapling);
1817  if (!opResult) {
1818  throw JSONRPCError(RPC_INVALID_PARAMETER, opResult.getError());
1819  }
1820 
1821  // Param 2: Minimum confirmations
1822  int nMinDepth = request.params.size() > 2 ? request.params[2].get_int() : 1;
1823  if (nMinDepth < 0) {
1824  throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
1825  }
1826 
1827  // Param 3: Fee
1828  // If not set, SaplingOperation will set the minimum fee (based on minRelayFee and tx size)
1829  if (request.params.size() > 3) {
1830  CAmount nFee = AmountFromValue(request.params[3]);
1831  if (nFee < 0) {
1832  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid fee. Must be positive.");
1833  } else if (nFee > 0) {
1834  // If the user-selected fee is not enough (or too much), the build operation will fail.
1835  operation.setFee(nFee);
1836  }
1837  // If nFee=0 leave the default (build operation will compute the minimum fee)
1838  }
1839 
1840  if (fromSapling && nMinDepth == 0) {
1841  throw JSONRPCError(RPC_INVALID_PARAMETER, "Minconf cannot be zero when sending from shield addr");
1842  }
1843 
1844  if (nMinDepth < 0) {
1845  throw JSONRPCError(RPC_INVALID_PARAMETER, "Minconf cannot be negative");
1846  }
1847 
1848  // Build the send operation
1849  OperationResult res = operation.setMinDepth(nMinDepth)
1850  ->setRecipients(recipients)
1851  ->build();
1852  if (!res) throw JSONRPCError(RPC_WALLET_ERROR, res.getError());
1853  return operation;
1854 }
1855 
1857 {
1858  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1859 
1860  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
1861  return NullUniValue;
1862 
1863  if (request.fHelp || request.params.size() < 2 || request.params.size() > 5)
1864  throw std::runtime_error(
1865  "shieldsendmany \"fromaddress\" [{\"address\":... ,\"amount\":...},...] ( minconf fee subtract_fee_from )\n"
1866  "\nSend to many recipients. Amounts are decimal numbers with at most 8 digits of precision."
1867  "\nChange generated from a transparent addr flows to a new transparent addr address, while change generated from a shield addr returns to itself."
1868  "\nWhen sending coinbase UTXOs to a shield addr, change is not allowed. The entire value of the UTXO(s) must be consumed."
1869  + HelpRequiringPassphrase(pwallet) + "\n"
1870 
1871  "\nArguments:\n"
1872  "1. \"fromaddress\" (string, required) The transparent addr or shield addr to send the funds from.\n"
1873  " It can also be the string \"from_transparent\"|\"from_shield\" to send the funds\n"
1874  " from any transparent|shield address available.\n"
1875  " Additionally, it can be the string \"from_trans_cold\" to select transparent funds,\n"
1876  " possibly including delegated coins, if needed.\n"
1877  "2. \"amounts\" (array, required) An array of json objects representing the amounts to send.\n"
1878  " [{\n"
1879  " \"address\":address (string, required) The address is a transparent addr or shield addr\n"
1880  " \"amount\":amount (numeric, required) The numeric amount in " + "PIV" + " is the value\n"
1881  " \"memo\":memo (string, optional) If the address is a shield addr, message string of max 512 bytes\n"
1882  " }, ... ]\n"
1883  "3. minconf (numeric, optional, default=1) Only use funds confirmed at least this many times.\n"
1884  "4. fee (numeric, optional), The fee amount to attach to this transaction.\n"
1885  " If not specified, or set to 0, the wallet will try to compute the minimum possible fee for a shield TX,\n"
1886  " based on the expected transaction size and the current value of -minRelayTxFee.\n"
1887  "5. subtract_fee_from (array, optional) A json array with addresses.\n"
1888  " The fee will be equally deducted from the amount of each selected address.\n"
1889  " Those recipients will receive less PIV than you enter in their corresponding amount field.\n"
1890  " If no addresses are specified here, the sender pays the fee.\n"
1891  " [\n"
1892  " \"address\" (string) Subtract fee from this address\n"
1893  " ,...\n"
1894  " ]\n"
1895  "\nResult:\n"
1896  "\"id\" (string) transaction hash in the network\n"
1897  "\nExamples:\n"
1898  + HelpExampleCli("shieldsendmany",
1899  "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\" '[{\"address\": \"ps1ra969yfhvhp73rw5ak2xvtcm9fkuqsnmad7qln79mphhdrst3lwu9vvv03yuyqlh42p42st47qd\" ,\"amount\": 5.0}]'")
1900  + HelpExampleRpc("shieldsendmany",
1901  "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\", [{\"address\": \"ps1ra969yfhvhp73rw5ak2xvtcm9fkuqsnmad7qln79mphhdrst3lwu9vvv03yuyqlh42p42st47qd\" ,\"amount\": 5.0}]")
1902  );
1903 
1904  EnsureWalletIsUnlocked(pwallet);
1905 
1906  // Make sure the results are valid at least up to the most recent block
1907  // the user could have gotten from another RPC command prior to now
1908  pwallet->BlockUntilSyncedToCurrentChain();
1909 
1910  SaplingOperation operation = CreateShieldedTransaction(pwallet, request);
1911  std::string txHash;
1912  auto res = operation.send(txHash);
1913  if (!res)
1914  throw JSONRPCError(RPC_WALLET_ERROR, res.getError());
1915  return txHash;
1916 }
1917 
1919 {
1920  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1921 
1922  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
1923  return NullUniValue;
1924 
1925  if (request.fHelp || request.params.size() < 2 || request.params.size() > 4)
1926  throw std::runtime_error(
1927  "rawshieldsendmany \"fromaddress\" [{\"address\":... ,\"amount\":...},...] ( minconf fee )\n"
1928  "\nCreates a transaction sending to many recipients (without committing it), and returns the hex string."
1929  "\nAmounts are decimal numbers with at most 8 digits of precision."
1930  "\nChange generated from a transparent addr flows to a new transparent addr address, while change generated from a shield addr returns to itself."
1931  "\nWhen sending coinbase UTXOs to a shield addr, change is not allowed. The entire value of the UTXO(s) must be consumed."
1932  + HelpRequiringPassphrase(pwallet) + "\n"
1933 
1934  "\nArguments:\n"
1935  "1. \"fromaddress\" (string, required) The transparent addr or shield addr to send the funds from.\n"
1936  " It can also be the string \"from_transparent\"|\"from_shield\" to send the funds\n"
1937  " from any transparent|shield address available.\n"
1938  " Additionally, it can be the string \"from_trans_cold\" to select transparent funds,\n"
1939  " possibly including delegated coins, if needed.\n"
1940  "2. \"amounts\" (array, required) An array of json objects representing the amounts to send.\n"
1941  " [{\n"
1942  " \"address\":address (string, required) The address is a transparent addr or shield addr\n"
1943  " \"amount\":amount (numeric, required) The numeric amount in " + "PIV" + " is the value\n"
1944  " \"memo\":memo (string, optional) If the address is a shield addr, message string of max 512 bytes\n"
1945  " }, ... ]\n"
1946  "3. minconf (numeric, optional, default=1) Only use funds confirmed at least this many times.\n"
1947  "4. fee (numeric, optional), The fee amount to attach to this transaction.\n"
1948  " If not specified, the wallet will try to compute the minimum possible fee for a shield TX,\n"
1949  " based on the expected transaction size and the current value of -minRelayTxFee.\n"
1950  "\nResult:\n"
1951  "\"transaction\" (string) hex string of the transaction\n"
1952 
1953  "\nExamples:\n"
1954  + HelpExampleCli("rawshieldsendmany",
1955  "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\" '[{\"address\": \"ps1ra969yfhvhp73rw5ak2xvtcm9fkuqsnmad7qln79mphhdrst3lwu9vvv03yuyqlh42p42st47qd\" ,\"amount\": 5.0}]'")
1956  + HelpExampleRpc("rawshieldsendmany",
1957  "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\", [{\"address\": \"ps1ra969yfhvhp73rw5ak2xvtcm9fkuqsnmad7qln79mphhdrst3lwu9vvv03yuyqlh42p42st47qd\" ,\"amount\": 5.0}]")
1958  );
1959 
1960  EnsureWalletIsUnlocked(pwallet);
1961 
1962  // Make sure the results are valid at least up to the most recent block
1963  // the user could have gotten from another RPC command prior to now
1964  pwallet->BlockUntilSyncedToCurrentChain();
1965 
1966  CTransaction tx = CreateShieldedTransaction(pwallet, request).getFinalTx();
1967  return EncodeHexTx(tx);
1968 }
1969 
1971 {
1972  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1973 
1974  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
1975  return NullUniValue;
1976 
1977  if (request.fHelp || !request.params.empty())
1978  throw std::runtime_error(
1979  "listaddressgroupings\n"
1980  "\nLists groups of addresses which have had their common ownership\n"
1981  "made public by common use as inputs or as the resulting change\n"
1982  "in past transactions\n"
1983 
1984  "\nResult:\n"
1985  "[\n"
1986  " [\n"
1987  " [\n"
1988  " \"pivxaddress\", (string) The pivx address\n"
1989  " amount, (numeric) The amount in PIV\n"
1990  " \"label\" (string, optional) The label\n"
1991  " ]\n"
1992  " ,...\n"
1993  " ]\n"
1994  " ,...\n"
1995  "]\n"
1996 
1997  "\nExamples:\n" +
1998  HelpExampleCli("listaddressgroupings", "") + HelpExampleRpc("listaddressgroupings", ""));
1999 
2000  // Make sure the results are valid at least up to the most recent block
2001  // the user could have gotten from another RPC command prior to now
2002  pwallet->BlockUntilSyncedToCurrentChain();
2003 
2004  LOCK2(cs_main, pwallet->cs_wallet);
2005 
2006  UniValue jsonGroupings(UniValue::VARR);
2007  std::map<CTxDestination, CAmount> balances = pwallet->GetAddressBalances();
2008  for (std::set<CTxDestination> grouping : pwallet->GetAddressGroupings()) {
2009  UniValue jsonGrouping(UniValue::VARR);
2010  for (CTxDestination address : grouping) {
2011  UniValue addressInfo(UniValue::VARR);
2012  addressInfo.push_back(EncodeDestination(address));
2013  addressInfo.push_back(ValueFromAmount(balances[address]));
2014  auto optAdd = pwallet->GetAddressBookEntry(address);
2015  if (optAdd) {
2016  addressInfo.push_back(optAdd->name);
2017  }
2018  jsonGrouping.push_back(addressInfo);
2019  }
2020  jsonGroupings.push_back(jsonGrouping);
2021  }
2022  return jsonGroupings;
2023 }
2024 
2026 {
2027  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2028 
2029  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
2030  return NullUniValue;
2031 
2032  if (request.fHelp || request.params.size() != 2)
2033  throw std::runtime_error(
2034  "signmessage \"address\" \"message\"\n"
2035  "\nSign a message with the private key of an address" +
2036  HelpRequiringPassphrase(pwallet) + "\n"
2037 
2038  "\nArguments:\n"
2039  "1. \"address\" (string, required) The pivx address to use for the private key.\n"
2040  "2. \"message\" (string, required) The message to create a signature of.\n"
2041 
2042  "\nResult:\n"
2043  "\"signature\" (string) The signature of the message encoded in base 64\n"
2044 
2045  "\nExamples:\n"
2046  "\nUnlock the wallet for 30 seconds\n" +
2047  HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
2048  "\nCreate the signature\n" +
2049  HelpExampleCli("signmessage", "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\" \"my message\"") +
2050  "\nVerify the signature\n" +
2051  HelpExampleCli("verifymessage", "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\" \"signature\" \"my message\"") +
2052  "\nAs json rpc\n" +
2053  HelpExampleRpc("signmessage", "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\", \"my message\""));
2054 
2055  LOCK2(cs_main, pwallet->cs_wallet);
2056 
2057  EnsureWalletIsUnlocked(pwallet);
2058 
2059  std::string strAddress = request.params[0].get_str();
2060  std::string strMessage = request.params[1].get_str();
2061 
2062  CTxDestination dest = DecodeDestination(strAddress);
2063  if (!IsValidDestination(dest))
2064  throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
2065 
2066  const CKeyID* keyID = boost::get<CKeyID>(&dest);
2067  if (!keyID)
2068  throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
2069 
2070  CKey key;
2071  if (!pwallet->GetKey(*keyID, key))
2072  throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
2073 
2074  std::vector<unsigned char> vchSig;
2075  if (!CMessageSigner::SignMessage(strMessage, vchSig, key)) {
2076  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
2077  }
2078 
2079  return EncodeBase64(vchSig);
2080 }
2081 
2083 {
2084  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2085 
2086  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
2087  return NullUniValue;
2088 
2089  if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
2090  throw std::runtime_error(
2091  "getreceivedbyaddress \"address\" ( minconf )\n"
2092  "\nReturns the total amount received by the given pivxaddress in transactions with at least minconf confirmations.\n"
2093 
2094  "\nArguments:\n"
2095  "1. \"address\" (string, required) The pivx address for transactions.\n"
2096  "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
2097 
2098  "\nResult:\n"
2099  "amount (numeric) The total amount in PIV received at this address.\n"
2100 
2101  "\nExamples:\n"
2102  "\nThe amount from transactions with at least 1 confirmation\n" +
2103  HelpExampleCli("getreceivedbyaddress", "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\"") +
2104  "\nThe amount including unconfirmed transactions, zero confirmations\n" +
2105  HelpExampleCli("getreceivedbyaddress", "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\" 0") +
2106  "\nThe amount with at least 6 confirmation, very safe\n" +
2107  HelpExampleCli("getreceivedbyaddress", "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\" 6") +
2108  "\nAs a json rpc call\n" +
2109  HelpExampleRpc("getreceivedbyaddress", "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\", 6"));
2110 
2111  // Make sure the results are valid at least up to the most recent block
2112  // the user could have gotten from another RPC command prior to now
2113  pwallet->BlockUntilSyncedToCurrentChain();
2114 
2115  LOCK2(cs_main, pwallet->cs_wallet);
2116  int nBlockHeight = chainActive.Height();
2117 
2118  // pivx address
2119  CTxDestination address = DecodeDestination(request.params[0].get_str());
2120  if (!IsValidDestination(address))
2121  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid PIVX address");
2122  CScript scriptPubKey = GetScriptForDestination(address);
2123  if (!IsMine(*pwallet, scriptPubKey))
2124  throw JSONRPCError(RPC_WALLET_ERROR, "Address not found in wallet");
2125 
2126  // Minimum confirmations
2127  int nMinDepth = 1;
2128  if (request.params.size() > 1)
2129  nMinDepth = request.params[1].get_int();
2130 
2131  // Tally
2132  CAmount nAmount = 0;
2133  for (const auto& entry : pwallet->mapWallet) {
2134  const CWalletTx& wtx = entry.second;
2135  if (wtx.IsCoinBase() || !IsFinalTx(wtx.tx, nBlockHeight))
2136  continue;
2137 
2138  for (const CTxOut& txout : wtx.tx->vout)
2139  if (txout.scriptPubKey == scriptPubKey)
2140  if (wtx.GetDepthInMainChain() >= nMinDepth)
2141  nAmount += txout.nValue;
2142  }
2143 
2144  return ValueFromAmount(nAmount);
2145 }
2146 
2147 
2149 {
2150  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2151 
2152  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
2153  return NullUniValue;
2154 
2155  if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
2156  throw std::runtime_error(
2157  "getreceivedbylabel \"label\" ( minconf )\n"
2158  "\nReturns the total amount received by addresses with <label> in transactions with at least [minconf] confirmations.\n"
2159 
2160  "\nArguments:\n"
2161  "1. \"label\" (string, required) The selected label, may be the default label using \"\".\n"
2162  "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
2163 
2164  "\nResult:\n"
2165  "amount (numeric) The total amount in PIV received for this label.\n"
2166 
2167  "\nExamples:\n"
2168  "\nAmount received by the default label with at least 1 confirmation\n" +
2169  HelpExampleCli("getreceivedbylabel", "\"\"") +
2170  "\nAmount received at the tabby label including unconfirmed amounts with zero confirmations\n" +
2171  HelpExampleCli("getreceivedbylabel", "\"tabby\" 0") +
2172  "\nThe amount with at least 6 confirmation, very safe\n" +
2173  HelpExampleCli("getreceivedbylabel", "\"tabby\" 6") +
2174  "\nAs a json rpc call\n" +
2175  HelpExampleRpc("getreceivedbylabel", "\"tabby\", 6"));
2176 
2177  // Make sure the results are valid at least up to the most recent block
2178  // the user could have gotten from another RPC command prior to now
2179  pwallet->BlockUntilSyncedToCurrentChain();
2180 
2181  LOCK2(cs_main, pwallet->cs_wallet);
2182  int nBlockHeight = chainActive.Height();
2183 
2184  // Minimum confirmations
2185  int nMinDepth = 1;
2186  if (request.params.size() > 1)
2187  nMinDepth = request.params[1].get_int();
2188 
2189  // Get the set of pub keys assigned to label
2190  std::string label = LabelFromValue(request.params[0]);
2191  std::set<CTxDestination> setAddress = pwallet->GetLabelAddresses(label);
2192 
2193  // Tally
2194  CAmount nAmount = 0;
2195  for (const auto& entry : pwallet->mapWallet) {
2196  const CWalletTx& wtx = entry.second;
2197  if (wtx.IsCoinBase() || !IsFinalTx(wtx.tx, nBlockHeight))
2198  continue;
2199 
2200  for (const CTxOut& txout : wtx.tx->vout) {
2201  CTxDestination address;
2202  if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwallet, address) && setAddress.count(address))
2203  if (wtx.GetDepthInMainChain() >= nMinDepth)
2204  nAmount += txout.nValue;
2205  }
2206  }
2207 
2208  return (double)nAmount / (double)COIN;
2209 }
2210 
2212 {
2213  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2214 
2215  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
2216  return NullUniValue;
2217 
2218  if (request.fHelp || (request.params.size() > 4 ))
2219  throw std::runtime_error(
2220  "getbalance ( minconf include_watchonly include_delegated include_shield )\n"
2221  "\nReturns the server's total available balance.\n"
2222  "The available balance is what the wallet considers currently spendable, and is\n"
2223  "thus affected by options which limit spendability such as -spendzeroconfchange.\n"
2224 
2225  "\nArguments:\n"
2226  "1. minconf (numeric, optional, default=0) Only include transactions confirmed at least this many times.\n"
2227  "2. include_watchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress')\n"
2228  "3. include_delegated (bool, optional, default=true) Also include balance delegated to cold stakers\n"
2229  "4. include_shield (bool, optional, default=true) Also include shield balance\n"
2230 
2231  "\nResult:\n"
2232  "amount (numeric) The total amount in PIV received for this wallet.\n"
2233 
2234  "\nExamples:\n"
2235  "\nThe total amount in the wallet\n" +
2236  HelpExampleCli("getbalance", "") +
2237  "\nThe total amount in the wallet, with at least 5 confirmations\n" +
2238  HelpExampleCli("getbalance", "6") +
2239  "\nAs a json rpc call\n" +
2240  HelpExampleRpc("getbalance", "6"));
2241 
2242  // Make sure the results are valid at least up to the most recent block
2243  // the user could have gotten from another RPC command prior to now
2244  pwallet->BlockUntilSyncedToCurrentChain();
2245 
2246  LOCK2(cs_main, pwallet->cs_wallet);
2247 
2248  const int paramsSize = request.params.size();
2249  const int nMinDepth = paramsSize > 0 ? request.params[0].get_int() : 0;
2250  bool fIncludeWatchOnly = paramsSize > 1 && request.params[1].get_bool();
2251  bool fIncludeDelegated = paramsSize <= 2 || request.params[2].get_bool();
2252  bool fIncludeShielded = paramsSize <= 3 || request.params[3].get_bool();
2253 
2254  isminefilter filter = ISMINE_SPENDABLE | (fIncludeWatchOnly ?
2255  (fIncludeShielded ? ISMINE_WATCH_ONLY_ALL : ISMINE_WATCH_ONLY) : ISMINE_NO);
2256  filter |= fIncludeDelegated ? ISMINE_SPENDABLE_DELEGATED : ISMINE_NO;
2257  filter |= fIncludeShielded ? ISMINE_SPENDABLE_SHIELDED : ISMINE_NO;
2258  return ValueFromAmount(pwallet->GetAvailableBalance(filter, true, nMinDepth));
2259 }
2260 
2262 {
2263  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2264 
2265  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
2266  return NullUniValue;
2267 
2268  if (request.fHelp || (request.params.size() != 0))
2269  throw std::runtime_error(
2270  "getcoldstakingbalance\n"
2271  "\nReturns the server's total available cold balance.\n"
2272 
2273  "\nResult:\n"
2274  "amount (numeric) The total amount in PIV received for this wallet in P2CS contracts.\n"
2275 
2276  "\nExamples:\n"
2277  "\nThe total amount in the wallet\n" +
2278  HelpExampleCli("getcoldstakingbalance", "") +
2279  "\nAs a json rpc call\n" +
2280  HelpExampleRpc("getcoldstakingbalance", "\"*\""));
2281 
2282  // Make sure the results are valid at least up to the most recent block
2283  // the user could have gotten from another RPC command prior to now
2284  pwallet->BlockUntilSyncedToCurrentChain();
2285 
2286  LOCK2(cs_main, pwallet->cs_wallet);
2287 
2288  return ValueFromAmount(pwallet->GetColdStakingBalance());
2289 }
2290 
2292 {
2293  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2294 
2295  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
2296  return NullUniValue;
2297 
2298  if (request.fHelp || (request.params.size() != 0))
2299  throw std::runtime_error(
2300  "getdelegatedbalance\n"
2301  "\nReturns the server's total available delegated balance (sum of all utxos delegated\n"
2302  "to a cold staking address to stake on behalf of addresses of this wallet).\n"
2303 
2304  "\nResult:\n"
2305  "amount (numeric) The total amount in PIV received for this wallet in P2CS contracts.\n"
2306 
2307  "\nExamples:\n"
2308  "\nThe total amount in the wallet\n" +
2309  HelpExampleCli("getdelegatedbalance", "") +
2310  "\nAs a json rpc call\n" +
2311  HelpExampleRpc("getdelegatedbalance", "\"*\""));
2312 
2313  // Make sure the results are valid at least up to the most recent block
2314  // the user could have gotten from another RPC command prior to now
2315  pwallet->BlockUntilSyncedToCurrentChain();
2316 
2317  LOCK2(cs_main, pwallet->cs_wallet);
2318 
2319  return ValueFromAmount(pwallet->GetDelegatedBalance());
2320 }
2321 
2323 {
2324  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2325 
2326  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
2327  return NullUniValue;
2328 
2329  if (request.fHelp || request.params.size() > 0)
2330  throw std::runtime_error(
2331  "getunconfirmedbalance\n"
2332  "Returns the server's total unconfirmed balance\n");
2333 
2334  // Make sure the results are valid at least up to the most recent block
2335  // the user could have gotten from another RPC command prior to now
2336  pwallet->BlockUntilSyncedToCurrentChain();
2337 
2338  LOCK2(cs_main, pwallet->cs_wallet);
2339 
2340  return ValueFromAmount(pwallet->GetUnconfirmedBalance());
2341 }
2342 
2343 /*
2344  * Only used for t->t transactions (via sendmany RPC)
2345  */
2346 static UniValue legacy_sendmany(CWallet* const pwallet, const UniValue& sendTo, int nMinDepth, std::string comment, bool fIncludeDelegated, const UniValue& subtractFeeFromAmount)
2347 {
2348  LOCK2(cs_main, pwallet->cs_wallet);
2349 
2350  if (!g_connman)
2351  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
2352 
2353  isminefilter filter = ISMINE_SPENDABLE | (fIncludeDelegated ? ISMINE_SPENDABLE_DELEGATED : ISMINE_NO);
2354 
2355  CTransactionRef txNew;
2356  std::set<CTxDestination> setAddress;
2357  std::vector<CRecipient> vecSend;
2358 
2359  CAmount totalAmount = 0;
2360  std::vector<std::string> keys = sendTo.getKeys();
2361  for (const std::string& name_ : keys) {
2362  bool isStaking = false;
2363  bool isExchange = false;
2364  CTxDestination dest = DecodeDestination(name_, isStaking, isExchange);
2365  if (!IsValidDestination(dest) || isStaking)
2366  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid PIVX address: ")+name_);
2367 
2368  if (setAddress.count(dest))
2369  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ")+name_);
2370  setAddress.insert(dest);
2371 
2372  CScript scriptPubKey = GetScriptForDestination(dest);
2373  CAmount nAmount = AmountFromValue(sendTo[name_]);
2374  totalAmount += nAmount;
2375 
2376  bool fSubtractFeeFromAmount = false;
2377  for (unsigned int idx = 0; idx < subtractFeeFromAmount.size(); idx++) {
2378  const UniValue& addr = subtractFeeFromAmount[idx];
2379  if (addr.get_str() == name_) {
2380  fSubtractFeeFromAmount = true;
2381  break;
2382  }
2383  }
2384 
2385  vecSend.emplace_back(scriptPubKey, nAmount, fSubtractFeeFromAmount);
2386  }
2387 
2388  // Check funds
2389  if (totalAmount > pwallet->GetLegacyBalance(filter, nMinDepth)) {
2390  throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Wallet has insufficient funds");
2391  }
2392 
2393  // Send
2394  CReserveKey keyChange(pwallet);
2395  CAmount nFeeRequired = 0;
2396  std::string strFailReason;
2397  int nChangePosInOut = -1;
2398  bool fCreated = pwallet->CreateTransaction(vecSend, txNew, keyChange, nFeeRequired, nChangePosInOut, strFailReason,
2399  nullptr, // coinControl
2400  true, // sign
2401  0, // nFeePay
2402  fIncludeDelegated,
2403  nullptr, // fStakeDelegationVoided
2404  0, // default extra size
2405  nMinDepth);
2406  if (!fCreated)
2407  throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
2408  const CWallet::CommitResult& res = pwallet->CommitTransaction(txNew, keyChange, g_connman.get());
2409  if (res.status != CWallet::CommitStatus::OK)
2410  throw JSONRPCError(RPC_WALLET_ERROR, res.ToString());
2411 
2412  // Set comment
2413  CWalletTx& wtx = pwallet->mapWallet.at(txNew->GetHash());
2414  if (!comment.empty()) {
2415  wtx.mapValue["comment"] = comment;
2416  }
2417 
2418  return wtx.GetHash().GetHex();
2419 }
2420 
2421 /*
2422  * This function uses [legacy_sendmany] in the background.
2423  * If any recipient is a shield address, instead it uses [shieldsendmany "from_transparent"].
2424  */
2426 {
2427  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2428 
2429  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
2430  return NullUniValue;
2431 
2432  if (request.fHelp || request.params.size() < 2 || request.params.size() > 6)
2433  throw std::runtime_error(
2434  "sendmany \"\" {\"address\":amount,...} ( minconf \"comment\" include_delegated )\n"
2435  "\nSend to multiple destinations. Recipients are transparent or shield PIVX addresses.\n"
2436  "\nAmounts are double-precision floating point numbers.\n"
2437  + HelpRequiringPassphrase(pwallet) + "\n"
2438 
2439  "\nArguments:\n"
2440  "1. \"dummy\" (string, required) Must be set to \"\" for backwards compatibility.\n"
2441  "2. \"amounts\" (string, required) A json object with addresses and amounts\n"
2442  " {\n"
2443  " \"address\":amount (numeric) The pivx address (either transparent or shield) is the key,\n"
2444  " the numeric amount in PIV is the value\n"
2445  " ,...\n"
2446  " }\n"
2447  "3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
2448  "4. \"comment\" (string, optional) A comment\n"
2449  "5. include_delegated (bool, optional, default=false) Also include balance delegated to cold stakers\n"
2450  "6. subtract_fee_from (array, optional) A json array with addresses.\n"
2451  " The fee will be equally deducted from the amount of each selected address.\n"
2452  " Those recipients will receive less PIV than you enter in their corresponding amount field.\n"
2453  " If no addresses are specified here, the sender pays the fee.\n"
2454  " [\n"
2455  " \"address\" (string) Subtract fee from this address\n"
2456  " ,...\n"
2457  " ]\n"
2458 
2459  "\nResult:\n"
2460  "\"transactionid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
2461  " the number of addresses.\n"
2462 
2463  "\nExamples:\n"
2464  "\nSend two amounts to two different addresses:\n" +
2465  HelpExampleCli("sendmany", "\"\" \"{\\\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\\\":0.01,\\\"DAD3Y6ivr8nPQLT1NEPX84DxGCw9jz9Jvg\\\":0.02}\"") +
2466  "\nSend two amounts to two different addresses setting the confirmation and comment:\n" +
2467  HelpExampleCli("sendmany", "\"\" \"{\\\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\\\":0.01,\\\"DAD3Y6ivr8nPQLT1NEPX84DxGCw9jz9Jvg\\\":0.02}\" 6 \"testing\"") +
2468  "\nSend to shield address:\n" +
2469  HelpExampleCli("sendmany", "\"\" \"{\\\"ps1u87kylcmn28yclnx2uy0psnvuhs2xn608ukm6n2nshrpg2nzyu3n62ls8j77m9cgp40dx40evej\\\":10}\"") +
2470  "\nAs a json rpc call\n" +
2471  HelpExampleRpc("sendmany", "\"\", \"{\\\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\\\":0.01,\\\"DAD3Y6ivr8nPQLT1NEPX84DxGCw9jz9Jvg\\\":0.02}\", 6, \"testing\"")
2472  );
2473 
2474  EnsureWalletIsUnlocked(pwallet);
2475 
2476  // Make sure the results are valid at least up to the most recent block
2477  // the user could have gotten from another RPC command prior to now
2478  pwallet->BlockUntilSyncedToCurrentChain();
2479 
2480  // Read Params
2481  if (!request.params[0].isNull() && !request.params[0].get_str().empty()) {
2482  throw JSONRPCError(RPC_INVALID_PARAMETER, "Dummy value must be set to \"\"");
2483  }
2484  const UniValue sendTo = request.params[1].get_obj();
2485  const int nMinDepth = request.params.size() > 2 ? request.params[2].get_int() : 1;
2486  const std::string comment = (request.params.size() > 3 && !request.params[3].isNull() && !request.params[3].get_str().empty()) ?
2487  request.params[3].get_str() : "";
2488  const bool fIncludeDelegated = (request.params.size() > 4 && request.params[4].get_bool());
2489 
2490  UniValue subtractFeeFromAmount(UniValue::VARR);
2491  if (request.params.size() > 5 && !request.params[5].isNull())
2492  subtractFeeFromAmount = request.params[5].get_array();
2493 
2494  // Check if any recipient address is shield
2495  bool fShieldSend = false;
2496  for (const std::string& key : sendTo.getKeys()) {
2497  bool isStaking = false, isExchange = false, isShielded = false;
2498  Standard::DecodeDestination(key, isStaking, isExchange, isShielded);
2499  if (isShielded) {
2500  fShieldSend = true;
2501  break;
2502  }
2503  }
2504 
2505  if (fShieldSend) {
2506  return ShieldSendManyTo(pwallet, sendTo, comment, "", nMinDepth, fIncludeDelegated, subtractFeeFromAmount);
2507  }
2508 
2509  // All recipients are transparent: use Legacy sendmany t->t
2510  return legacy_sendmany(pwallet, sendTo, nMinDepth, comment, fIncludeDelegated, subtractFeeFromAmount);
2511 }
2512 
2513 // Defined in rpc/misc.cpp
2514 extern CScript _createmultisig_redeemScript(CWallet* const pwallet, const UniValue& params);
2515 
2517 {
2518  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2519 
2520  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
2521  return NullUniValue;
2522 
2523  if (request.fHelp || request.params.size() < 2 || request.params.size() > 3)
2524  throw std::runtime_error(
2525  "addmultisigaddress nrequired [\"key\",...] ( \"label\" )\n"
2526  "\nAdd a nrequired-to-sign multisignature address to the wallet. Requires a new wallet backup.\n"
2527  "Each key is a PIVX address or hex-encoded public key.\n"
2528  "If 'label' is specified, assign address to that label.\n"
2529 
2530  "\nArguments:\n"
2531  "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
2532  "2. \"keys\" (string, required) A json array of pivx addresses or hex-encoded public keys\n"
2533  " [\n"
2534  " \"address\" (string) pivx address or hex-encoded public key\n"
2535  " ...,\n"
2536  " ]\n"
2537  "3. \"label\" (string, optional) A label to assign the addresses to.\n"
2538 
2539  "\nResult:\n"
2540  "\"pivxaddress\" (string) A pivx address associated with the keys.\n"
2541 
2542  "\nExamples:\n"
2543  "\nAdd a multisig address from 2 addresses\n" +
2544  HelpExampleCli("addmultisigaddress", "2 \"[\\\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\\\",\\\"DAD3Y6ivr8nPQLT1NEPX84DxGCw9jz9Jvg\\\"]\"") +
2545  "\nAs json rpc call\n" +
2546  HelpExampleRpc("addmultisigaddress", "2, \"[\\\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\\\",\\\"DAD3Y6ivr8nPQLT1NEPX84DxGCw9jz9Jvg\\\"]\""));
2547 
2548  LOCK2(cs_main, pwallet->cs_wallet);
2549 
2550  std::string label;
2551  if (request.params.size() > 2)
2552  label = LabelFromValue(request.params[2]);
2553 
2554  // Construct using pay-to-script-hash:
2555  CScript inner = _createmultisig_redeemScript(pwallet, request.params);
2556  CScriptID innerID(inner);
2557  pwallet->AddCScript(inner);
2558 
2559  pwallet->SetAddressBook(innerID, label, AddressBook::AddressBookPurpose::SEND);
2560  return EncodeDestination(innerID);
2561 }
2562 
2563 
2564 struct tallyitem {
2566  int nConf;
2567  std::vector<uint256> txids;
2570  {
2571  nAmount = 0;
2572  nConf = std::numeric_limits<int>::max();
2573  fIsWatchonly = false;
2574  }
2575 };
2576 
2577 static UniValue ListReceived(CWallet* const pwallet, const UniValue& params, bool by_label, int nBlockHeight)
2578 {
2579  // Minimum confirmations
2580  int nMinDepth = 1;
2581  if (params.size() > 0)
2582  nMinDepth = params[0].get_int();
2583 
2584  // Whether to include empty labels
2585  bool fIncludeEmpty = false;
2586  if (params.size() > 1)
2587  fIncludeEmpty = params[1].get_bool();
2588 
2590  if (params.size() > 2)
2591  if (params[2].get_bool())
2592  filter = filter | ISMINE_WATCH_ONLY;
2593 
2594  bool has_filtered_address = false;
2595  CTxDestination filtered_address = CNoDestination();
2596  if (!by_label && params.size() > 3) {
2597  CTxDestination dest = DecodeDestination(params[3].get_str());
2598  if (!IsValidDestination(dest)) {
2599  throw JSONRPCError(RPC_WALLET_ERROR, "address_filter parameter was invalid");
2600  }
2601  filtered_address = dest;
2602  has_filtered_address = true;
2603  }
2604 
2605  // Tally
2606  std::map<CTxDestination, tallyitem> mapTally;
2607  for (const auto& entry : pwallet->mapWallet) {
2608  const CWalletTx& wtx = entry.second;
2609 
2610  if (!IsFinalTx(wtx.tx, nBlockHeight)) {
2611  continue;
2612  }
2613 
2614  int nDepth = wtx.GetDepthInMainChain();
2615  if (nDepth < nMinDepth) {
2616  continue;
2617  }
2618 
2619  for (const CTxOut& txout : wtx.tx->vout) {
2620  CTxDestination address;
2621  if (!ExtractDestination(txout.scriptPubKey, address)) {
2622  continue;
2623  }
2624 
2625  if (has_filtered_address && !(filtered_address == address)) {
2626  continue;
2627  }
2628 
2629  isminefilter mine = IsMine(*pwallet, address);
2630  if (!(mine & filter)) {
2631  continue;
2632  }
2633 
2634  tallyitem& item = mapTally[address];
2635  item.nAmount += txout.nValue;
2636  item.nConf = std::min(item.nConf, nDepth);
2637  item.txids.push_back(wtx.GetHash());
2638  if (mine & ISMINE_WATCH_ONLY)
2639  item.fIsWatchonly = true;
2640  }
2641  }
2642 
2643  // Create mapAddressBook iterator
2644  // If we aren't filtering, go from begin() to end()
2645  auto itAddr = pwallet->NewAddressBookIterator();
2646  // If we are filtering, find() the applicable entry
2647  if (has_filtered_address) {
2648  itAddr.SetFilter(filtered_address);
2649  }
2650 
2651  // Reply
2652  UniValue ret(UniValue::VARR);
2653  std::map<std::string, tallyitem> label_tally;
2654 
2655  for (auto& itAddrBook = itAddr; itAddrBook.IsValid(); itAddrBook.Next()) {
2656 
2657  auto* dest = itAddrBook.GetCTxDestKey();
2658  if (!dest) continue;
2659 
2660  const auto &address = *dest;
2661  const std::string &label = itAddrBook.GetValue().name;
2662  auto it = mapTally.find(address);
2663  if (it == mapTally.end() && !fIncludeEmpty) {
2664  continue;
2665  }
2666 
2667  CAmount nAmount = 0;
2668  int nConf = std::numeric_limits<int>::max();
2669  bool fIsWatchonly = false;
2670  if (it != mapTally.end()) {
2671  nAmount = (*it).second.nAmount;
2672  nConf = (*it).second.nConf;
2673  fIsWatchonly = (*it).second.fIsWatchonly;
2674  }
2675 
2676  if (by_label) {
2677  tallyitem& _item = label_tally[label];
2678  _item.nAmount += nAmount;
2679  _item.nConf = std::min(_item.nConf, nConf);
2680  _item.fIsWatchonly = fIsWatchonly;
2681  } else {
2682  UniValue obj(UniValue::VOBJ);
2683  if (fIsWatchonly)
2684  obj.pushKV("involvesWatchonly", true);
2685  obj.pushKV("address", EncodeDestination(address, AddressBook::IsColdStakingPurpose(label), AddressBook::IsExchangePurpose(label)));
2686  obj.pushKV("amount", ValueFromAmount(nAmount));
2687  if (nConf == std::numeric_limits<int>::max()) nConf = 0;
2688  obj.pushKV("confirmations", nConf);
2689  obj.pushKV("bcconfirmations", nConf); // DEPRECATED in 4.3.99
2690  obj.pushKV("label", label);
2691  UniValue transactions(UniValue::VARR);
2692  if (it != mapTally.end()) {
2693  for (const uint256 &item : (*it).second.txids) {
2694  transactions.push_back(item.GetHex());
2695  }
2696  }
2697  obj.pushKV("txids", transactions);
2698  ret.push_back(obj);
2699  }
2700  }
2701 
2702  if (by_label) {
2703  for (const auto& entry : label_tally) {
2704  CAmount nAmount = entry.second.nAmount;
2705  int nConf = entry.second.nConf;
2706  UniValue obj(UniValue::VOBJ);
2707  if (entry.second.fIsWatchonly)
2708  obj.pushKV("involvesWatchonly", true);
2709  obj.pushKV("amount", ValueFromAmount(nAmount));
2710  obj.pushKV("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf));
2711  obj.pushKV("label", entry.first);
2712  ret.push_back(obj);
2713  }
2714  }
2715 
2716  return ret;
2717 }
2718 
2720 {
2721  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2722 
2723  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
2724  return NullUniValue;
2725 
2726  if (request.fHelp || request.params.size() > 4)
2727  throw std::runtime_error(
2728  "listreceivedbyaddress ( minconf include_empty include_watchonly filter)\n"
2729  "\nList balances by receiving address.\n"
2730 
2731  "\nArguments:\n"
2732  "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
2733  "2. include_empty (numeric, optional, default=false) Whether to include addresses that haven't received any payments.\n"
2734  "3. include_watchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
2735  "4. filter (string, optional) If present, only return information on this address.\n"
2736 
2737  "\nResult:\n"
2738  "[\n"
2739  " {\n"
2740  " \"involvesWatchonly\" : \"true\", (bool) Only returned if imported addresses were involved in transaction\n"
2741  " \"address\" : \"receivingaddress\", (string) The receiving address\n"
2742  " \"amount\" : x.xxx, (numeric) The total amount in PIV received by the address\n"
2743  " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n"
2744  " \"bcconfirmations\" : n, (numeric) DEPRECATED: Will be removed in a future release\n"
2745  " \"label\" : \"label\", (string) The label of the receiving address. The default label is \"\".\n"
2746  " }\n"
2747  " ,...\n"
2748  "]\n"
2749 
2750  "\nExamples:\n" +
2751  HelpExampleCli("listreceivedbyaddress", "") +
2752  HelpExampleCli("listreceivedbyaddress", "6 true") +
2753  HelpExampleRpc("listreceivedbyaddress", "6, true, true") +
2754  HelpExampleRpc("listreceivedbyaddress", "6, true, true, \"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\""));
2755 
2756  // Make sure the results are valid at least up to the most recent block
2757  // the user could have gotten from another RPC command prior to now
2758  pwallet->BlockUntilSyncedToCurrentChain();
2759 
2760  LOCK2(cs_main, pwallet->cs_wallet);
2761  int nBlockHeight = chainActive.Height();
2762  return ListReceived(pwallet, request.params, false, nBlockHeight);
2763 }
2764 
2766 {
2767  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2768 
2769  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
2770  return NullUniValue;
2771 
2772  if (request.fHelp || request.params.size()==0 || request.params.size() >2)
2773  throw std::runtime_error(
2774  "listreceivedbyshieldaddress \"address\" ( minconf )\n"
2775  "\nReturn a list of amounts received by a shield addr belonging to the node's wallet.\n"
2776 
2777  "\nArguments:\n"
2778  "1. \"address\" (string) The private address.\n"
2779  "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
2780 
2781  "\nResult:\n"
2782  "{\n"
2783  " \"txid\": \"txid\", (string) the transaction id\n"
2784  " \"amount\": xxxxx, (numeric) the amount of value in the note\n"
2785  " \"memo\": xxxxx, (string) hexadecimal string representation of memo field\n"
2786  " \"confirmations\" : n, (numeric) the number of confirmations\n"
2787  " \"blockheight\": n, (numeric) The block height containing the transaction\n"
2788  " \"blockindex\": n, (numeric) The block index containing the transaction.\n"
2789  " \"blocktime\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
2790  " \"outindex\" (sapling) : n, (numeric) the output index\n"
2791  " \"change\": true|false, (boolean) true if the address that received the note is also one of the sending addresses\n"
2792  "}\n"
2793 
2794  "\nExamples:\n"
2795  + HelpExampleCli("listreceivedbyshieldaddress", "\"ps1ra969yfhvhp73rw5ak2xvtcm9fkuqsnmad7qln79mphhdrst3lwu9vvv03yuyqlh42p42st47qd\"")
2796  + HelpExampleRpc("listreceivedbyshieldaddress", "\"ps1ra969yfhvhp73rw5ak2xvtcm9fkuqsnmad7qln79mphhdrst3lwu9vvv03yuyqlh42p42st47qd\"")
2797  );
2798 
2799  // Make sure the results are valid at least up to the most recent block
2800  // the user could have gotten from another RPC command prior to now
2801  pwallet->BlockUntilSyncedToCurrentChain();
2802 
2803  LOCK2(cs_main, pwallet->cs_wallet);
2804 
2805  int nMinDepth = 1;
2806  if (request.params.size() > 1) {
2807  nMinDepth = request.params[1].get_int();
2808  }
2809  if (nMinDepth < 0) {
2810  throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
2811  }
2812 
2813  // Check that the from address is valid.
2814  auto fromaddress = request.params[0].get_str();
2815 
2816  auto zaddr = KeyIO::DecodeSaplingPaymentAddress(fromaddress);
2817  if (!zaddr) {
2818  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid addr.");
2819  }
2820  libzcash::SaplingPaymentAddress shieldAddr = *zaddr;
2821 
2822  auto sspkm = pwallet->GetSaplingScriptPubKeyMan();
2823  // Visitor to support Sapling addrs
2824  if (!sspkm->PaymentAddressBelongsToWallet(shieldAddr)) {
2825  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, shield addr spending key or viewing key not found.");
2826  }
2827 
2828  UniValue result(UniValue::VARR);
2829  std::vector<SaplingNoteEntry> saplingEntries;
2830  sspkm->GetFilteredNotes(saplingEntries, zaddr, nMinDepth, false, false);
2831 
2832  std::set<std::pair<libzcash::PaymentAddress, uint256>> nullifierSet;
2833  bool hasSpendingKey = pwallet->HaveSpendingKeyForPaymentAddress(shieldAddr);
2834  if (hasSpendingKey) {
2835  nullifierSet = sspkm->GetNullifiersForAddresses({*zaddr});
2836  }
2837 
2838  for (const SaplingNoteEntry& entry : saplingEntries) {
2839  UniValue obj(UniValue::VOBJ);
2840  obj.pushKV("txid", entry.op.hash.ToString());
2841  obj.pushKV("amount", ValueFromAmount(CAmount(entry.note.value())));
2842  obj.pushKV("memo", HexStrTrimmed(entry.memo));
2843  obj.pushKV("outindex", (int)entry.op.n);
2844  obj.pushKV("confirmations", entry.confirmations);
2845 
2846  int height = 0;
2847  int index = -1;
2848  int64_t time = 0;
2849 
2850  auto it = pwallet->mapWallet.find(entry.op.hash);
2851  if (it != pwallet->mapWallet.end()) {
2852  const CWalletTx& wtx = it->second;
2853  if (!wtx.m_confirm.hashBlock.IsNull())
2854  height = mapBlockIndex[wtx.m_confirm.hashBlock]->nHeight;
2855  index = wtx.m_confirm.nIndex;
2856  time = wtx.GetTxTime();
2857  }
2858 
2859  obj.pushKV("blockheight", height);
2860  obj.pushKV("blockindex", index);
2861  obj.pushKV("blocktime", time);
2862 
2863  if (hasSpendingKey) {
2864  obj.pushKV("change", sspkm->IsNoteSaplingChange(nullifierSet, entry.address, entry.op));
2865  }
2866  result.push_back(obj);
2867  }
2868  return result;
2869 }
2870 
2872 {
2873  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2874 
2875  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
2876  return NullUniValue;
2877 
2878  if (request.fHelp || request.params.size() > 3)
2879  throw std::runtime_error(
2880  "listreceivedbylabel ( minconf include_empty include_watchonly)\n"
2881  "\nList received transactions by label.\n"
2882 
2883  "\nArguments:\n"
2884  "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
2885  "2. include_empty (boolean, optional, default=false) Whether to include labels that haven't received any payments.\n"
2886  "3. include_watchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
2887 
2888  "\nResult:\n"
2889  "[\n"
2890  " {\n"
2891  " \"involvesWatchonly\" : \"true\", (bool) Only returned if imported addresses were involved in transaction\n"
2892  " \"amount\" : x.xxx, (numeric) The total amount received by addresses with this label\n"
2893  " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n"
2894  " \"bcconfirmations\" : n, (numeric) DEPRECATED: Will be removed in a future release\n"
2895  " \"label\" : \"label\" (string) The label of the receiving address. The default label is \"\".\n"
2896  " }\n"
2897  " ,...\n"
2898  "]\n"
2899 
2900  "\nExamples:\n" +
2901  HelpExampleCli("listreceivedbylabel", "") + HelpExampleCli("listreceivedbylabel", "6 true") + HelpExampleRpc("listreceivedbylabel", "6, true, true"));
2902 
2903  // Make sure the results are valid at least up to the most recent block
2904  // the user could have gotten from another RPC command prior to now
2905  pwallet->BlockUntilSyncedToCurrentChain();
2906 
2907  LOCK2(cs_main, pwallet->cs_wallet);
2908  int nBlockHeight = chainActive.Height();
2909  return ListReceived(pwallet, request.params, true, nBlockHeight);
2910 }
2911 
2913 {
2914  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2915 
2916  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
2917  return NullUniValue;
2918 
2919  if (request.fHelp || request.params.size() > 1)
2920  throw std::runtime_error(
2921  "listcoldutxos ( not_whitelisted )\n"
2922  "\nList P2CS unspent outputs received by this wallet as cold-staker-\n"
2923 
2924  "\nArguments:\n"
2925  "1. not_whitelisted (boolean, optional, default=false) Whether to exclude P2CS from whitelisted delegators.\n"
2926 
2927  "\nResult:\n"
2928  "[\n"
2929  " {\n"
2930  " \"txid\" : \"true\", (string) The transaction id of the P2CS utxo\n"
2931  " \"txidn\" : n (numeric) The output number of the P2CS utxo\n"
2932  " \"amount\" : x.xxx, (numeric) The amount of the P2CS utxo\n"
2933  " \"confirmations\" : n (numeric) The number of confirmations of the P2CS utxo\n"
2934  " \"cold-staker\" : \"address\" (string) The cold-staker address of the P2CS utxo\n"
2935  " \"coin-owner\" : \"address\" (string) The coin-owner address of the P2CS utxo\n"
2936  " \"whitelisted\" : \"true\" (boolean) \"true\"/\"false\" coin-owner in delegator whitelist\n"
2937  " }\n"
2938  " ,...\n"
2939  "]\n"
2940 
2941  "\nExamples:\n" +
2942  HelpExampleCli("listcoldutxos", "") + HelpExampleCli("listcoldutxos", "true"));
2943 
2944  // Make sure the results are valid at least up to the most recent block
2945  // the user could have gotten from another RPC command prior to now
2946  pwallet->BlockUntilSyncedToCurrentChain();
2947 
2948  LOCK2(cs_main, pwallet->cs_wallet);
2949 
2950  bool fExcludeWhitelisted = false;
2951  if (request.params.size() > 0)
2952  fExcludeWhitelisted = request.params[0].get_bool();
2953  UniValue results(UniValue::VARR);
2954 
2955  for (const auto& entry : pwallet->mapWallet) {
2956  const uint256& wtxid = entry.first;
2957  const CWalletTx* pcoin = &entry.second;
2958  if (!CheckFinalTx(pcoin->tx) || !pcoin->IsTrusted())
2959  continue;
2960 
2961  // if this tx has no unspent P2CS outputs for us, skip it
2962  if(pcoin->GetColdStakingCredit() == 0 && pcoin->GetStakeDelegationCredit() == 0)
2963  continue;
2964 
2965  for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++) {
2966  const CTxOut& out = pcoin->tx->vout[i];
2967  isminetype mine = pwallet->IsMine(out);
2968  if (!bool(mine & ISMINE_COLD) && !bool(mine & ISMINE_SPENDABLE_DELEGATED))
2969  continue;
2970  txnouttype type;
2971  std::vector<CTxDestination> addresses;
2972  int nRequired;
2973  if (!ExtractDestinations(out.scriptPubKey, type, addresses, nRequired))
2974  continue;
2975  const bool fWhitelisted = pwallet->HasAddressBook(addresses[1]) > 0;
2976  if (fExcludeWhitelisted && fWhitelisted)
2977  continue;
2978  UniValue entry(UniValue::VOBJ);
2979  entry.pushKV("txid", wtxid.GetHex());
2980  entry.pushKV("txidn", (int)i);
2981  entry.pushKV("amount", ValueFromAmount(out.nValue));
2982  entry.pushKV("confirmations", pcoin->GetDepthInMainChain());
2983  entry.pushKV("cold-staker", EncodeDestination(addresses[0], CChainParams::STAKING_ADDRESS));
2984  entry.pushKV("coin-owner", EncodeDestination(addresses[1]));
2985  entry.pushKV("whitelisted", fWhitelisted ? "true" : "false");
2986  results.push_back(entry);
2987  }
2988  }
2989 
2990  return results;
2991 }
2992 
2993 static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
2994 {
2995  if (IsValidDestination(dest))
2996  entry.pushKV("address", EncodeDestination(dest));
2997 }
2998 
2999 static void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
3000 {
3002 
3003  CAmount nFee;
3004  std::list<COutputEntry> listReceived;
3005  std::list<COutputEntry> listSent;
3006 
3007  wtx.GetAmounts(listReceived, listSent, nFee, filter);
3008 
3009  bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY);
3010 
3011  // Sent
3012  if ((!listSent.empty() || nFee != 0)) {
3013  for (const COutputEntry& s : listSent) {
3014  UniValue entry(UniValue::VOBJ);
3015  if (involvesWatchonly || (::IsMine(*pwallet, s.destination) & ISMINE_WATCH_ONLY))
3016  entry.pushKV("involvesWatchonly", true);
3017  MaybePushAddress(entry, s.destination);
3018  entry.pushKV("category", "send");
3019  entry.pushKV("amount", ValueFromAmount(-s.amount));
3020  if (pwallet->HasAddressBook(s.destination)) {
3021  entry.pushKV("label", pwallet->GetNameForAddressBookEntry(s.destination));
3022  }
3023  entry.pushKV("vout", s.vout);
3024  entry.pushKV("fee", ValueFromAmount(-nFee));
3025  if (fLong)
3026  WalletTxToJSON(wtx, entry);
3027  ret.push_back(entry);
3028  }
3029  }
3030 
3031  // Received
3032  int depth = wtx.GetDepthInMainChain();
3033  if (listReceived.size() > 0 && depth >= nMinDepth) {
3034  for (const COutputEntry& r : listReceived) {
3035  std::string label;
3036  if (pwallet->HasAddressBook(r.destination))
3037  label = pwallet->GetNameForAddressBookEntry(r.destination);
3038  UniValue entry(UniValue::VOBJ);
3039  if (involvesWatchonly || (::IsMine(*pwallet, r.destination) & ISMINE_WATCH_ONLY))
3040  entry.pushKV("involvesWatchonly", true);
3041  MaybePushAddress(entry, r.destination);
3042  if (wtx.IsCoinBase()) {
3043  if (depth < 1)
3044  entry.pushKV("category", "orphan");
3045  else if (wtx.GetBlocksToMaturity() > 0)
3046  entry.pushKV("category", "immature");
3047  else
3048  entry.pushKV("category", "generate");
3049  } else {
3050  entry.pushKV("category", "receive");
3051  }
3052  entry.pushKV("amount", ValueFromAmount(r.amount));
3053  if (pwallet->HasAddressBook(r.destination)) {
3054  entry.pushKV("label", label);
3055  }
3056  entry.pushKV("vout", r.vout);
3057  if (fLong)
3058  WalletTxToJSON(wtx, entry);
3059  ret.push_back(entry);
3060  }
3061  }
3062 }
3063 
3065 {
3066  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
3067 
3068  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
3069  return NullUniValue;
3070 
3071  if (request.fHelp || request.params.size() > 6) throw std::runtime_error(
3072  "listtransactions ( \"dummy\" count from include_watchonly include_delegated include_cold)\n"
3073  "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions.\n"
3074 
3075  "\nArguments:\n"
3076  "1. \"dummy\" (string, optional) If set, should be \"*\" for backwards compatibility.\n"
3077  "2. count (numeric, optional, default=10) The number of transactions to return\n"
3078  "3. from (numeric, optional, default=0) The number of transactions to skip\n"
3079  "4. include_watchonly (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')\n"
3080  "5. include_delegated (bool, optional, default=true) Also include balance delegated to cold stakers\n"
3081  "6. include_cold (bool, optional, default=true) Also include delegated balance received as cold-staker by this node\n"
3082 
3083  "\nResult:\n"
3084  "[\n"
3085  " {\n"
3086  " \"address\":\"pivxaddress\", (string) The pivx address of the transaction.\n"
3087  " \"category\":\"category\", (string) The transaction category (send|receive|orphan|immature|generate).\n"
3088  " \"amount\": x.xxx, (numeric) The amount in PIV. This is negative for the 'send' category, and positive\n"
3089  " for the 'receive' category,\n"
3090  " \"vout\" : n, (numeric) the vout value\n"
3091  " \"fee\": x.xxx, (numeric) The amount of the fee in PIV. This is negative and only available for the \n"
3092  " 'send' category of transactions.\n"
3093  " \"confirmations\": n, (numeric) The number of blockchain confirmations for the transaction. Available for 'send'\n"
3094  " 'receive' category of transactions. Negative confirmations indicate the\n"
3095  " transaction conflicts with the block chain\n"
3096  " \"bcconfirmations\" : n, (numeric) DEPRECATED: Will be removed in a future release\n"
3097  " \"trusted\": xxx (bool) Whether we consider the outputs of this unconfirmed transaction safe to spend.\n"
3098  " and 'receive' category of transactions.\n"
3099  " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive'\n"
3100  " category of transactions.\n"
3101  " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive'\n"
3102  " category of transactions.\n"
3103  " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
3104  " \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
3105  " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
3106  " for 'send' and 'receive' category of transactions.\n"
3107  " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
3108  " }\n"
3109  "]\n"
3110 
3111  "\nExamples:\n"
3112  "\nList the most recent 10 transactions in the systems\n" +
3113  HelpExampleCli("listtransactions", "") +
3114  "\nList transactions 100 to 120\n" +
3115  HelpExampleCli("listtransactions", "\"*\" 20 100") +
3116  "\nAs a json rpc call\n" +
3117  HelpExampleRpc("listtransactions", "\"*\", 20, 100")
3118  );
3119 
3120  // Make sure the results are valid at least up to the most recent block
3121  // the user could have gotten from another RPC command prior to now
3122  pwallet->BlockUntilSyncedToCurrentChain();
3123 
3124  LOCK2(cs_main, pwallet->cs_wallet);
3125 
3126  if (!request.params[0].isNull() && request.params[0].get_str() != "*") {
3127  throw JSONRPCError(RPC_INVALID_PARAMETER, "Dummy value must be set to \"*\"");
3128  }
3129  int nCount = 10;
3130  if (request.params.size() > 1)
3131  nCount = request.params[1].get_int();
3132  int nFrom = 0;
3133  if (request.params.size() > 2)
3134  nFrom = request.params[2].get_int();
3135  isminefilter filter = ISMINE_SPENDABLE;
3136  if ( request.params.size() > 3 && request.params[3].get_bool() )
3137  filter = filter | ISMINE_WATCH_ONLY;
3138  if ( !(request.params.size() > 4) || request.params[4].get_bool() )
3139  filter = filter | ISMINE_SPENDABLE_DELEGATED;
3140  if ( !(request.params.size() > 5) || request.params[5].get_bool() )
3141  filter = filter | ISMINE_COLD;
3142 
3143  if (nCount < 0)
3144  throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
3145  if (nFrom < 0)
3146  throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
3147 
3148  UniValue ret(UniValue::VARR);
3149 
3150  const CWallet::TxItems & txOrdered = pwallet->wtxOrdered;
3151 
3152  // iterate backwards until we have nCount items to return:
3153  for (CWallet::TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
3154  CWalletTx* const pwtx = (*it).second;
3155  ListTransactions(pwallet, *pwtx, 0, true, ret, filter);
3156  if ((int)ret.size() >= (nCount + nFrom)) break;
3157  }
3158  // ret is newest to oldest
3159 
3160  if (nFrom > (int)ret.size())
3161  nFrom = ret.size();
3162  if ((nFrom + nCount) > (int)ret.size())
3163  nCount = ret.size() - nFrom;
3164 
3165  std::vector<UniValue> arrTmp = ret.getValues();
3166 
3167  std::vector<UniValue>::iterator first = arrTmp.begin();
3168  std::advance(first, nFrom);
3169  std::vector<UniValue>::iterator last = arrTmp.begin();
3170  std::advance(last, nFrom+nCount);
3171 
3172  if (last != arrTmp.end()) arrTmp.erase(last, arrTmp.end());
3173  if (first != arrTmp.begin()) arrTmp.erase(arrTmp.begin(), first);
3174 
3175  std::reverse(arrTmp.begin(), arrTmp.end()); // Return oldest to newest
3176 
3177  ret.clear();
3178  ret.setArray();
3179  ret.push_backV(arrTmp);
3180 
3181  return ret;
3182 }
3183 
3185 {
3186  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
3187 
3188  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
3189  return NullUniValue;
3190 
3191  if (request.fHelp || request.params.size() > 3)
3192  throw std::runtime_error(
3193  "listsinceblock ( \"blockhash\" target_confirmations include_watchonly)\n"
3194  "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted\n"
3195 
3196  "\nArguments:\n"
3197  "1. \"blockhash\" (string, optional) The block hash to list transactions since\n"
3198  "2. target_confirmations: (numeric, optional) The confirmations required, must be 1 or more\n"
3199  "3. include_watchonly: (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')"
3200 
3201  "\nResult:\n"
3202  "{\n"
3203  " \"transactions\": [\n"
3204  " \"address\":\"pivxaddress\", (string) The pivx address of the transaction. Not present for move transactions (category = move).\n"
3205  " \"category\":\"send|receive\", (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
3206  " \"amount\": x.xxx, (numeric) The amount in PIV. This is negative for the 'send' category, and for the 'move' category for moves \n"
3207  " outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
3208  " \"vout\" : n, (numeric) the vout value\n"
3209  " \"fee\": x.xxx, (numeric) The amount of the fee in PIV. This is negative and only available for the 'send' category of transactions.\n"
3210  " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n"
3211  " \"bcconfirmations\" : n, (numeric) DEPRECATED: Will be removed in a future release\n"
3212  " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
3213  " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
3214  " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
3215  " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
3216  " \"time\": xxx, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
3217  " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
3218  " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
3219  " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
3220  " \"to\": \"...\", (string) If a comment to is associated with the transaction.\n"
3221  " ],\n"
3222  " \"lastblock\": \"lastblockhash\" (string) The hash of the last block\n"
3223  "}\n"
3224 
3225  "\nExamples:\n" +
3226  HelpExampleCli("listsinceblock", "") +
3227  HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6") +
3228  HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6"));
3229 
3230  // Make sure the results are valid at least up to the most recent block
3231  // the user could have gotten from another RPC command prior to now
3232  pwallet->BlockUntilSyncedToCurrentChain();
3233 
3234  LOCK2(cs_main, pwallet->cs_wallet);
3235 
3236  CBlockIndex* pindex = nullptr;
3237  int target_confirms = 1;
3239 
3240  if (request.params.size() > 0) {
3241  uint256 blockId(ParseHashV(request.params[0], "blockhash"));
3242  pindex = LookupBlockIndex(blockId);
3243  }
3244 
3245  if (request.params.size() > 1) {
3246  target_confirms = request.params[1].get_int();
3247 
3248  if (target_confirms < 1)
3249  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
3250  }
3251 
3252  if (request.params.size() > 2)
3253  if (request.params[2].get_bool())
3254  filter = filter | ISMINE_WATCH_ONLY;
3255 
3256  int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
3257 
3258  UniValue transactions(UniValue::VARR);
3259 
3260  for (const auto& entry : pwallet->mapWallet) {
3261  const CWalletTx& tx = entry.second;
3262 
3263  if (depth == -1 || tx.GetDepthInMainChain() < depth)
3264  ListTransactions(pwallet, tx, 0, true, transactions, filter);
3265  }
3266 
3267  CBlockIndex* pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
3268  uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : UINT256_ZERO;
3269 
3270  UniValue ret(UniValue::VOBJ);
3271  ret.pushKV("transactions", transactions);
3272  ret.pushKV("lastblock", lastblock.GetHex());
3273 
3274  return ret;
3275 }
3276 
3278 {
3279  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
3280 
3281  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
3282  return NullUniValue;
3283 
3284  if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
3285  throw std::runtime_error(
3286  "gettransaction \"txid\" ( include_watchonly )\n"
3287  "\nGet detailed information about in-wallet transaction \"txid\"\n"
3288 
3289  "\nArguments:\n"
3290  "1. \"txid\" (string, required) The transaction id\n"
3291  "2. \"include_watchonly\" (bool, optional, default=false) Whether to include watchonly addresses in balance calculation and details[]\n"
3292 
3293  "\nResult:\n"
3294  "{\n"
3295  " \"amount\" : x.xxx, (numeric) The transaction amount in PIV\n"
3296  " \"confirmations\" : n, (numeric) The number of confirmations\n"
3297  " \"bcconfirmations\" : n, (numeric) DEPRECATED: Will be removed in a future release\n"
3298  " \"blockhash\" : \"hash\", (string) The block hash\n"
3299  " \"blockindex\" : xx, (numeric) The block index\n"
3300  " \"blocktime\" : ttt, (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n"
3301  " \"txid\" : \"transactionid\", (string) The transaction id.\n"
3302  " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n"
3303  " \"timereceived\" : ttt, (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n"
3304  " \"details\" : [\n"
3305  " {\n"
3306  " \"address\" : \"pivxaddress\", (string) The pivx address involved in the transaction\n"
3307  " \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n"
3308  " \"amount\" : x.xxx (numeric) The amount in PIV\n"
3309  " \"label\" : \"label\", (string) A comment for the address/transaction, if any\n"
3310  " \"vout\" : n, (numeric) the vout value\n"
3311  " }\n"
3312  " ,...\n"
3313  " ],\n"
3314  " \"hex\" : \"data\" (string) Raw data for transaction\n"
3315  "}\n"
3316 
3317  "\nExamples:\n" +
3318  HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"") +
3319  HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true") +
3320  HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\""));
3321 
3322  // Make sure the results are valid at least up to the most recent block
3323  // the user could have gotten from another RPC command prior to now
3324  pwallet->BlockUntilSyncedToCurrentChain();
3325 
3326  LOCK2(cs_main, pwallet->cs_wallet);
3327 
3328  uint256 hash(ParseHashV(request.params[0], "txid"));
3329 
3331  if (request.params.size() > 1)
3332  if (request.params[1].get_bool())
3333  filter = filter | ISMINE_WATCH_ONLY;
3334 
3335  UniValue entry(UniValue::VOBJ);
3336  auto it = pwallet->mapWallet.find(hash);
3337  if (it == pwallet->mapWallet.end()) {
3338  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
3339  }
3340  const CWalletTx& wtx = it->second;
3341 
3342  CAmount nCredit = wtx.GetCredit(filter);
3343  CAmount nDebit = wtx.GetDebit(filter);
3344  CAmount nNet = nCredit - nDebit;
3345  CAmount nFee = (wtx.IsFromMe(filter) ? wtx.tx->GetValueOut() - nDebit : 0);
3346 
3347  entry.pushKV("amount", ValueFromAmount(nNet - nFee));
3348  if (wtx.IsFromMe(filter))
3349  entry.pushKV("fee", ValueFromAmount(nFee));
3350 
3351  WalletTxToJSON(wtx, entry);
3352 
3353  UniValue details(UniValue::VARR);
3354  ListTransactions(pwallet, wtx, 0, false, details, filter);
3355  entry.pushKV("details", details);
3356 
3357  std::string strHex = EncodeHexTx(*wtx.tx);
3358  entry.pushKV("hex", strHex);
3359 
3360  return entry;
3361 }
3362 
3364 {
3365  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
3366 
3367  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
3368  return NullUniValue;
3369 
3370  if (request.fHelp || request.params.size() != 1)
3371  throw std::runtime_error(
3372  "abandontransaction \"txid\"\n"
3373  "\nMark in-wallet transaction \"txid\" as abandoned\n"
3374  "This will mark this transaction and all its in-wallet descendants as abandoned which will allow\n"
3375  "for their inputs to be respent. It can be used to replace \"stuck\" or evicted transactions.\n"
3376  "It only works on transactions which are not included in a block and are not currently in the mempool.\n"
3377  "It has no effect on transactions which are already abandoned.\n"
3378  "\nArguments:\n"
3379  "1. \"txid\" (string, required) The transaction id\n"
3380  "\nResult:\n"
3381  "\nExamples:\n"
3382  + HelpExampleCli("abandontransaction",
3383  "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
3384  + HelpExampleRpc("abandontransaction",
3385  "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
3386  );
3387 
3388  // Make sure the results are valid at least up to the most recent block
3389  // the user could have gotten from another RPC command prior to now
3390  pwallet->BlockUntilSyncedToCurrentChain();
3391 
3392  LOCK2(cs_main, pwallet->cs_wallet);
3393 
3394  uint256 hash(ParseHashV(request.params[0], "txid"));
3395 
3396  if (!pwallet->mapWallet.count(hash))
3397  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
3398  if (!pwallet->AbandonTransaction(hash))
3399  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not eligible for abandonment");
3400 
3401  return NullUniValue;
3402 }
3403 
3404 
3406 {
3407  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
3408 
3409  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
3410  return NullUniValue;
3411 
3412  if (request.fHelp || request.params.size() != 1)
3413  throw std::runtime_error(
3414  "backupwallet \"destination\"\n"
3415  "\nSafely copies wallet file to destination, which can be a directory or a path with filename.\n"
3416 
3417  "\nArguments:\n"
3418  "1. \"destination\" (string) The destination directory or file\n"
3419 
3420  "\nExamples:\n" +
3421  HelpExampleCli("backupwallet", "\"backup.dat\"") + HelpExampleRpc("backupwallet", "\"backup.dat\""));
3422 
3423  // Make sure the results are valid at least up to the most recent block
3424  // the user could have gotten from another RPC command prior to now
3425  pwallet->BlockUntilSyncedToCurrentChain();
3426 
3427  LOCK2(cs_main, pwallet->cs_wallet);
3428 
3429  std::string strDest = request.params[0].get_str();
3430  if (!pwallet->BackupWallet(strDest))
3431  throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
3432 
3433  return NullUniValue;
3434 }
3435 
3436 
3438 {
3439  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
3440 
3441  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
3442  return NullUniValue;
3443 
3444  if (request.fHelp || request.params.size() > 1)
3445  throw std::runtime_error(
3446  "keypoolrefill ( newsize )\n"
3447  "\nFills the keypool." +
3448  HelpRequiringPassphrase(pwallet) + "\n"
3449 
3450  "\nArguments\n"
3451  "1. newsize (numeric, optional, default=100) The new keypool size\n"
3452 
3453  "\nExamples:\n" +
3454  HelpExampleCli("keypoolrefill", "") + HelpExampleRpc("keypoolrefill", ""));
3455 
3456  LOCK2(cs_main, pwallet->cs_wallet);
3457 
3458  // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
3459  unsigned int kpSize = 0;
3460  if (request.params.size() > 0) {
3461  if (request.params[0].get_int() < 0)
3462  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
3463  kpSize = (unsigned int)request.params[0].get_int();
3464  }
3465 
3466  EnsureWalletIsUnlocked(pwallet);
3467  pwallet->TopUpKeyPool(kpSize);
3468 
3469  if (pwallet->GetKeyPoolSize() < kpSize)
3470  throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
3471 
3472  return NullUniValue;
3473 }
3474 
3475 
3476 static void LockWallet(CWallet* pWallet)
3477 {
3478  LOCK(pWallet->cs_wallet);
3479  pWallet->nRelockTime = 0;
3480  pWallet->fWalletUnlockStaking = false;
3481  pWallet->Lock();
3482 }
3483 
3485 {
3486  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
3487 
3488  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
3489  return NullUniValue;
3490 
3491  if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) {
3492  throw std::runtime_error(
3493  "walletpassphrase \"passphrase\" timeout ( staking_only )\n"
3494  "\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
3495  "This is needed prior to performing transactions related to private keys such as sending PIVs\n"
3496 
3497  "\nArguments:\n"
3498  "1. \"passphrase\" (string, required) The wallet passphrase\n"
3499  "2. timeout (numeric, required) The time to keep the decryption key in seconds.\n"
3500  "3. staking_only (boolean, optional, default=false) If is true sending functions are disabled."
3501 
3502  "\nNote:\n"
3503  "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
3504  "time that overrides the old one. A timeout of \"0\" unlocks until the wallet is closed.\n"
3505 
3506  "\nExamples:\n"
3507  "\nUnlock the wallet for 60 seconds\n" +
3508  HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
3509  "\nUnlock the wallet for 60 seconds but allow staking only\n" +
3510  HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60 true") +
3511  "\nLock the wallet again (before 60 seconds)\n" +
3512  HelpExampleCli("walletlock", "") +
3513  "\nAs json rpc call\n" +
3514  HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60"));
3515  }
3516 
3517  LOCK2(cs_main, pwallet->cs_wallet);
3518 
3519  if (request.fHelp)
3520  return true;
3521  if (!pwallet->IsCrypted())
3522  throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
3523 
3524  // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
3525  SecureString strWalletPass;
3526  strWalletPass.reserve(100);
3527  // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
3528  // Alternately, find a way to make request.params[0] mlock()'d to begin with.
3529  strWalletPass = request.params[0].get_str().c_str();
3530 
3531  bool stakingOnly = false;
3532  if (request.params.size() == 3)
3533  stakingOnly = request.params[2].get_bool();
3534 
3535  if (!pwallet->IsLocked() && pwallet->fWalletUnlockStaking && stakingOnly)
3536  throw JSONRPCError(RPC_WALLET_ALREADY_UNLOCKED, "Error: Wallet is already unlocked.");
3537 
3538  // Get the timeout
3539  int64_t nSleepTime = request.params[1].get_int64();
3540  // Timeout cannot be negative, otherwise it will relock immediately
3541  if (nSleepTime < 0) {
3542  throw JSONRPCError(RPC_INVALID_PARAMETER, "Timeout cannot be negative.");
3543  }
3544  // Clamp timeout
3545  constexpr int64_t MAX_SLEEP_TIME = 100000000; // larger values trigger a macos/libevent bug?
3546  if (nSleepTime > MAX_SLEEP_TIME) {
3547  nSleepTime = MAX_SLEEP_TIME;
3548  }
3549 
3550  if (!pwallet->Unlock(strWalletPass, stakingOnly))
3551  throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
3552 
3553  pwallet->TopUpKeyPool();
3554 
3555  if (nSleepTime > 0) {
3556  pwallet->nRelockTime = GetTime () + nSleepTime;
3557  RPCRunLater (strprintf("lockwallet(%s)", pwallet->GetName()), std::bind (LockWallet, pwallet), nSleepTime);
3558  }
3559 
3560  return NullUniValue;
3561 }
3562 
3563 
3565 {
3566  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
3567 
3568  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
3569  return NullUniValue;
3570 
3571  if (request.fHelp || request.params.size() != 2) {
3572  throw std::runtime_error(
3573  "walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
3574  "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n"
3575 
3576  "\nArguments:\n"
3577  "1. \"oldpassphrase\" (string) The current passphrase\n"
3578  "2. \"newpassphrase\" (string) The new passphrase\n"
3579 
3580  "\nExamples:\n" +
3581  HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"") + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\""));
3582  }
3583 
3584  LOCK2(cs_main, pwallet->cs_wallet);
3585 
3586  if (request.fHelp)
3587  return true;
3588  if (!pwallet->IsCrypted())
3589  throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
3590 
3591  // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
3592  // Alternately, find a way to make request.params[0] mlock()'d to begin with.
3593  SecureString strOldWalletPass;
3594  strOldWalletPass.reserve(100);
3595  strOldWalletPass = request.params[0].get_str().c_str();
3596 
3597  SecureString strNewWalletPass;
3598  strNewWalletPass.reserve(100);
3599  strNewWalletPass = request.params[1].get_str().c_str();
3600 
3601  if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
3602  throw std::runtime_error(
3603  "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
3604  "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
3605 
3606  if (!pwallet->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
3607  throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
3608 
3609  return NullUniValue;
3610 }
3611 
3612 
3614 {
3615  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
3616 
3617  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
3618  return NullUniValue;
3619 
3620  if (request.fHelp || !request.params.empty()) {
3621  throw std::runtime_error(
3622  "walletlock\n"
3623  "\nRemoves the wallet encryption key from memory, locking the wallet.\n"
3624  "After calling this method, you will need to call walletpassphrase again\n"
3625  "before being able to call any methods which require the wallet to be unlocked.\n"
3626 
3627  "\nExamples:\n"
3628  "\nSet the passphrase for 2 minutes to perform a transaction\n" +
3629  HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +
3630  "\nPerform a send (requires passphrase set)\n" +
3631  HelpExampleCli("sendtoaddress", "\"DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6\" 1.0") +
3632  "\nClear the passphrase since we are done before 2 minutes is up\n" +
3633  HelpExampleCli("walletlock", "") +
3634  "\nAs json rpc call\n" +
3635  HelpExampleRpc("walletlock", ""));
3636  }
3637 
3638  // Make sure the results are valid at least up to the most recent block
3639  // the user could have gotten from another RPC command prior to now
3640  pwallet->BlockUntilSyncedToCurrentChain();
3641 
3642  LOCK2(cs_main, pwallet->cs_wallet);
3643 
3644  if (request.fHelp)
3645  return true;
3646  if (!pwallet->IsCrypted())
3647  throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");
3648 
3649  pwallet->Lock();
3650  pwallet->nRelockTime = 0;
3651 
3652  return NullUniValue;
3653 }
3654 
3655 
3657 {
3658  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
3659 
3660  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
3661  return NullUniValue;
3662 
3663  if (request.fHelp || request.params.size() != 1) {
3664  throw std::runtime_error(
3665  "encryptwallet \"passphrase\"\n"
3666  "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
3667  "After this, any calls that interact with private keys such as sending or signing \n"
3668  "will require the passphrase to be set prior the making these calls.\n"
3669  "Use the walletpassphrase call for this, and then walletlock call.\n"
3670  "If the wallet is already encrypted, use the walletpassphrasechange call.\n"
3671 
3672  "\nArguments:\n"
3673  "1. \"passphrase\" (string) The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long.\n"
3674 
3675  "\nExamples:\n"
3676  "\nEncrypt you wallet\n" +
3677  HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
3678  "\nNow set the passphrase to use the wallet, such as for signing or sending PIVs\n" +
3679  HelpExampleCli("walletpassphrase", "\"my pass phrase\"") +
3680  "\nNow we can so something like sign\n" +
3681  HelpExampleCli("signmessage", "\"pivxaddress\" \"test message\"") +
3682  "\nNow lock the wallet again by removing the passphrase\n" +
3683  HelpExampleCli("walletlock", "") +
3684  "\nAs a json rpc call\n" +
3685  HelpExampleRpc("encryptwallet", "\"my pass phrase\""));
3686  }
3687 
3688  LOCK2(cs_main, pwallet->cs_wallet);
3689 
3690  if (request.fHelp)
3691  return true;
3692  if (pwallet->IsCrypted())
3693  throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
3694 
3695  // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
3696  // Alternately, find a way to make request.params[0] mlock()'d to begin with.
3697  SecureString strWalletPass;
3698  strWalletPass.reserve(100);
3699  strWalletPass = request.params[0].get_str().c_str();
3700 
3701  if (strWalletPass.length() < 1)
3702  throw std::runtime_error(
3703  "encryptwallet <passphrase>\n"
3704  "Encrypts the wallet with <passphrase>.");
3705 
3706  if (!pwallet->EncryptWallet(strWalletPass))
3707  throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet.");
3708 
3709  return "wallet encrypted; The keypool has been flushed, you need to make a new backup.";
3710 }
3711 
3713 {
3714  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
3715 
3716  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
3717  return NullUniValue;
3718 
3719  if (request.fHelp || request.params.size() > 6)
3720  throw std::runtime_error(
3721  "listunspent ( minconf maxconf [\"address\",...] watchonly_config [query_options] include_unsafe)\n"
3722  "\nReturns array of unspent transaction outputs\n"
3723  "with between minconf and maxconf (inclusive) confirmations.\n"
3724  "Optionally filter to only include txouts paid to specified addresses.\n"
3725  "Results are an array of Objects, each of which has:\n"
3726  "{txid, vout, scriptPubKey, amount, confirmations, spendable}\n"
3727 
3728  "\nArguments:\n"
3729  "1. minconf (numeric, optional, default=1) The minimum confirmations to filter\n"
3730  "2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter\n"
3731  "3. \"addresses\" (string) A json array of pivx addresses to filter\n"
3732  " [\n"
3733  " \"address\" (string) pivx address\n"
3734  " ,...\n"
3735  " ]\n"
3736  "4. watchonly_config (numeric, optional, default=1) 1 = list regular unspent transactions, 2 = list all unspent transactions (including watchonly)\n"
3737  "5. query_options (json, optional) JSON with query options\n"
3738  " {\n"
3739  " \"minimumAmount\" (numeric or string, default=0) Minimum value of each UTXO in " + CURRENCY_UNIT + "\n"
3740  " \"maximumAmount\" (numeric or string, default=unlimited) Maximum value of each UTXO in " + CURRENCY_UNIT + "\n"
3741  " \"maximumCount\" (numeric or string, default=unlimited) Maximum number of UTXOs\n"
3742  " \"minimumSumAmount\" (numeric or string, default=unlimited) Minimum sum value of all UTXOs in " + CURRENCY_UNIT + "\n"
3743  " }\n"
3744  "6. include_unsafe (bool, optional, default=true) Include outputs that are not safe to spend\n"
3745  " See description of \"safe\" attribute below.\n"
3746 
3747  "\nResult\n"
3748  "[ (array of json object)\n"
3749  " {\n"
3750  " \"txid\" : \"txid\", (string) the transaction id\n"
3751  " \"generated\" : true|false (boolean) true if txout is a coinstake transaction output\n"
3752  " \"vout\" : n, (numeric) the vout value\n"
3753  " \"address\" : \"address\", (string) the pivx address\n"
3754  " \"label\" : \"label\", (string) The associated label, or \"\" for the default label\n"
3755  " \"scriptPubKey\" : \"key\", (string) the script key\n"
3756  " \"redeemScript\" : \"key\", (string) the redeemscript key\n"
3757  " \"amount\" : x.xxx, (numeric) the transaction amount in PIV\n"
3758  " \"confirmations\" : n, (numeric) The number of confirmations\n"
3759  " \"spendable\" : true|false (boolean) Whether we have the private keys to spend this output\n"
3760  " \"solvable\" : xxx (boolean) Whether we know how to spend this output, ignoring the lack of keys\n"
3761  " \"safe\" : xxx (boolean) Whether this output is considered safe to spend. Unconfirmed transactions\n"
3762  " from outside keys and unconfirmed replacement transactions are considered unsafe\n"
3763  " and are not eligible for spending by fundrawtransaction and sendtoaddress.\n"
3764  " }\n"
3765  " ,...\n"
3766  "]\n"
3767 
3768  "\nExamples\n" +
3769  HelpExampleCli("listunspent", "") + HelpExampleCli("listunspent", "6 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
3770  + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
3771  + HelpExampleCli("listunspent", "6 9999999 '[]' 1 '{ \"minimumAmount\": 0.005 }'")
3772  + HelpExampleCli("listunspent", "6 9999999 '[]' 1 '{ \"minimumAmount\": 0.005 }' false")
3773  + HelpExampleRpc("listunspent", "6, 9999999, [] , 1, { \"minimumAmount\": 0.005 } ")
3774  );
3775 
3776  // Make sure the results are valid at least up to the most recent block
3777  // the user could have gotten from another RPC command prior to now
3778  pwallet->BlockUntilSyncedToCurrentChain();
3779 
3780  int nMinDepth = 1;
3781  if (request.params.size() > 0) {
3783  nMinDepth = request.params[0].get_int();
3784  }
3785 
3786  int nMaxDepth = 9999999;
3787  if (request.params.size() > 1) {
3789  nMaxDepth = request.params[1].get_int();
3790  }
3791 
3792  CWallet::AvailableCoinsFilter coinFilter;
3793 
3794  std::set<CTxDestination> destinations;
3795  if (request.params.size() > 2) {
3797  UniValue inputs = request.params[2].get_array();
3798  for (unsigned int inx = 0; inx < inputs.size(); inx++) {
3799  const UniValue& input = inputs[inx];
3800  CTxDestination dest = DecodeDestination(input.get_str());
3801  if (!IsValidDestination(dest))
3802  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid PIVX address: ") + input.get_str());
3803  if (destinations.count(dest))
3804  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + input.get_str());
3805  destinations.insert(dest);
3806  }
3807  coinFilter.onlyFilteredDest = &destinations;
3808  }
3809 
3810  // List watch only utxo
3811  int nWatchonlyConfig = 1;
3812  if(request.params.size() > 3) {
3814  nWatchonlyConfig = request.params[3].get_int();
3815  if (nWatchonlyConfig > 2 || nWatchonlyConfig < 1)
3816  nWatchonlyConfig = 1;
3817  }
3818 
3819  if (request.params.size() > 4) {
3820  const UniValue& options = request.params[4].get_obj();
3821 
3822  RPCTypeCheckObj(options,
3823  {
3824  {"minimumAmount", UniValueType()},
3825  {"maximumAmount", UniValueType()},
3826  {"minimumSumAmount", UniValueType()},
3827  {"maximumCount", UniValueType(UniValue::VNUM)},
3828  },
3829  true, true);
3830 
3831  if (options.exists("minimumAmount")) {
3832  coinFilter.nMinOutValue = AmountFromValue(options["minimumAmount"]);
3833  }
3834 
3835  if (options.exists("maximumAmount")) {
3836  coinFilter.nMaxOutValue = AmountFromValue(options["maximumAmount"]);
3837  }
3838 
3839  if (options.exists("minimumSumAmount")) {
3840  coinFilter.nMinimumSumAmount = AmountFromValue(options["minimumSumAmount"]);
3841  }
3842 
3843  if (options.exists("maximumCount"))
3844  coinFilter.nMaximumCount = options["maximumCount"].get_int64();
3845  }
3846 
3847  CCoinControl coinControl;
3848  coinControl.fAllowWatchOnly = nWatchonlyConfig == 2;
3849 
3850  bool include_unsafe = request.params.size() < 6 || request.params[5].get_bool();
3851  coinFilter.fOnlySafe = !include_unsafe;
3852 
3853  UniValue results(UniValue::VARR);
3854  std::vector<COutput> vecOutputs;
3855 
3856  LOCK2(cs_main, pwallet->cs_wallet);
3857  pwallet->AvailableCoins(&vecOutputs, &coinControl, coinFilter);
3858  for (const COutput& out : vecOutputs) {
3859  if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
3860  continue;
3861 
3862  UniValue entry(UniValue::VOBJ);
3863  entry.pushKV("txid", out.tx->GetHash().GetHex());
3864  entry.pushKV("vout", out.i);
3865  entry.pushKV("generated", out.tx->IsCoinStake() || out.tx->IsCoinBase());
3866  CTxDestination address;
3867  const CScript& scriptPubKey = out.tx->tx->vout[out.i].scriptPubKey;
3868  if (ExtractDestination(scriptPubKey, address)) {
3869  entry.pushKV("address", EncodeDestination(address));
3870  if (pwallet->HasAddressBook(address)) {
3871  entry.pushKV("label", pwallet->GetNameForAddressBookEntry(address));
3872  }
3873  if (scriptPubKey.IsPayToScriptHash()) {
3874  const CScriptID& hash = boost::get<CScriptID>(address);
3875  CScript redeemScript;
3876  if (pwallet->GetCScript(hash, redeemScript))
3877  entry.pushKV("redeemScript", HexStr(redeemScript));
3878  }
3879  }
3880  entry.pushKV("scriptPubKey", HexStr(scriptPubKey));
3881  entry.pushKV("amount", ValueFromAmount(out.tx->tx->vout[out.i].nValue));
3882  entry.pushKV("confirmations", out.nDepth);
3883  entry.pushKV("spendable", out.fSpendable);
3884  entry.pushKV("solvable", out.fSolvable);
3885  entry.pushKV("safe", out.fSafe);
3886  results.push_back(entry);
3887  }
3888 
3889  return results;
3890 }
3891 
3893 {
3894  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
3895 
3896  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
3897  return NullUniValue;
3898 
3899  if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
3900  throw std::runtime_error(
3901  "fundrawtransaction \"hexstring\" ( options )\n"
3902  "\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
3903  "This will not modify existing inputs, and will add one change output to the outputs.\n"
3904  "Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n"
3905  "The inputs added will not be signed, use signrawtransaction for that.\n"
3906  "Note that all existing inputs must have their previous output transaction be in the wallet.\n"
3907  "Note that all inputs selected must be of standard form and P2SH scripts must be "
3908  "in the wallet using importaddress or addmultisigaddress (to calculate fees).\n"
3909  "You can see whether this is the case by checking the \"solvable\" field in the listunspent output.\n"
3910  "Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n"
3911 
3912  "\nArguments:\n"
3913  "1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
3914  "2. options (object, optional)\n"
3915  " {\n"
3916  " \"changeAddress\" (string, optional, default pool address) The PIVX address to receive the change\n"
3917  " \"changePosition\" (numeric, optional, default random) The index of the change output\n"
3918  " \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n"
3919  " \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n"
3920  " \"feeRate\" (numeric, optional, default 0=estimate) Set a specific feerate (PIV per KB)\n"
3921  " \"subtractFeeFromOutputs\" (array, optional) A json array of integers.\n"
3922  " The fee will be equally deducted from the amount of each specified output.\n"
3923  " The outputs are specified by their zero-based index, before any change output is added.\n"
3924  " Those recipients will receive less PIV than you enter in their corresponding amount field.\n"
3925  " If no outputs are specified here, the sender pays the fee.\n"
3926  " [vout_index,...]\n"
3927  " }\n"
3928  "\nResult:\n"
3929  "{\n"
3930  " \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n"
3931  " \"fee\": n, (numeric) The fee added to the transaction\n"
3932  " \"changepos\": n (numeric) The position of the added change output, or -1\n"
3933  "}\n"
3934  "\"hex\" \n"
3935  "\nExamples:\n"
3936  "\nCreate a transaction with no inputs\n"
3937  + HelpExampleCli("createrawtransaction", "\"[]\" \"{\\\"myaddress\\\":0.01}\"") +
3938  "\nAdd sufficient unsigned inputs to meet the output value\n"
3939  + HelpExampleCli("fundrawtransaction", "\"rawtransactionhex\"") +
3940  "\nSign the transaction\n"
3941  + HelpExampleCli("signrawtransaction", "\"fundedtransactionhex\"") +
3942  "\nSend the transaction\n"
3943  + HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
3944  );
3945 
3946  // Make sure the results are valid at least up to the most recent block
3947  // the user could have gotten from another RPC command prior to now
3948  pwallet->BlockUntilSyncedToCurrentChain();
3949 
3950  RPCTypeCheck(request.params, {UniValue::VSTR});
3951 
3952  CTxDestination changeAddress = CNoDestination();
3953  int changePosition = -1;
3954  bool includeWatching = false;
3955  bool lockUnspents = false;
3956  UniValue subtractFeeFromOutputs;
3957  std::set<int> setSubtractFeeFromOutputs;
3958  CFeeRate feeRate = CFeeRate(0);
3959  bool overrideEstimatedFeerate = false;
3960 
3961  if (request.params.size() > 1) {
3962  RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ});
3963  UniValue options = request.params[1];
3964  RPCTypeCheckObj(options,
3965  {
3966  {"changeAddress", UniValueType(UniValue::VSTR)},
3967  {"changePosition", UniValueType(UniValue::VNUM)},
3968  {"includeWatching", UniValueType(UniValue::VBOOL)},
3969  {"lockUnspents", UniValueType(UniValue::VBOOL)},
3970  {"feeRate", UniValueType()}, // will be checked below
3971  {"subtractFeeFromOutputs", UniValueType(UniValue::VARR)},
3972  },
3973  true, true);
3974 
3975  if (options.exists("changeAddress")) {
3976  changeAddress = DecodeDestination(options["changeAddress"].get_str());
3977 
3978  if (!IsValidDestination(changeAddress))
3979  throw JSONRPCError(RPC_INVALID_PARAMETER, "changeAddress must be a valid PIVX address");
3980  }
3981 
3982  if (options.exists("changePosition"))
3983  changePosition = options["changePosition"].get_int();
3984 
3985  if (options.exists("includeWatching"))
3986  includeWatching = options["includeWatching"].get_bool();
3987 
3988  if (options.exists("lockUnspents"))
3989  lockUnspents = options["lockUnspents"].get_bool();
3990 
3991  if (options.exists("feeRate")) {
3992  feeRate = CFeeRate(AmountFromValue(options["feeRate"]));
3993  overrideEstimatedFeerate = true;
3994  }
3995 
3996  if (options.exists("subtractFeeFromOutputs")) {
3997  subtractFeeFromOutputs = options["subtractFeeFromOutputs"].get_array();
3998  }
3999  }
4000 
4001  // parse hex string from parameter
4002  CMutableTransaction origTx;
4003  if (!DecodeHexTx(origTx, request.params[0].get_str()))
4004  throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
4005 
4006  if (origTx.vout.size() == 0)
4007  throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output");
4008 
4009  if (changePosition != -1 && (changePosition < 0 || (unsigned int) changePosition > origTx.vout.size()))
4010  throw JSONRPCError(RPC_INVALID_PARAMETER, "changePosition out of bounds");
4011 
4012  for (unsigned int idx = 0; idx < subtractFeeFromOutputs.size(); idx++) {
4013  int pos = subtractFeeFromOutputs[idx].get_int();
4014  if (setSubtractFeeFromOutputs.count(pos))
4015  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, duplicated position: %d", pos));
4016  if (pos < 0)
4017  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, negative position: %d", pos));
4018  if (pos >= int(origTx.vout.size()))
4019  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, position too large: %d", pos));
4020  setSubtractFeeFromOutputs.insert(pos);
4021  }
4022 
4023  CMutableTransaction tx(origTx);
4024  CAmount nFeeOut;
4025  std::string strFailReason;
4026  if(!pwallet->FundTransaction(tx, nFeeOut, overrideEstimatedFeerate, feeRate,
4027  changePosition, strFailReason, includeWatching,
4028  lockUnspents, setSubtractFeeFromOutputs, changeAddress)) {
4029  throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
4030  }
4031 
4032  UniValue result(UniValue::VOBJ);
4033  result.pushKV("hex", EncodeHexTx(tx));
4034  result.pushKV("changepos", changePosition);
4035  result.pushKV("fee", ValueFromAmount(nFeeOut));
4036 
4037  return result;
4038 }
4039 
4041 {
4042  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
4043 
4044  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
4045  return NullUniValue;
4046 
4047  if (request.fHelp || request.params.size() < 2 || request.params.size() > 3)
4048  throw std::runtime_error(
4049  "lockunspent unlock transparent [{\"txid\":\"txid\",\"vout\":n},...]\n"
4050  "\nUpdates list of temporarily unspendable outputs.\n"
4051  "Temporarily lock (unlock=false) or unlock (unlock=true) specified transparent (transparent=true) or shielded (transparent=false) transaction outputs.\n"
4052  "A locked transaction output will not be chosen by automatic coin selection, when spending PIVs.\n"
4053  "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
4054  "is always cleared (by virtue of process exit) when a node stops or fails.\n"
4055  "Also see the listunspent call\n"
4056 
4057  "\nArguments:\n"
4058  "1. unlock (boolean, required) Whether to unlock (true) or lock (false) the specified transactions\n"
4059  "2. transparent (boolean, required) Whether the given transaction outputs are transparent (true) or shielded (false)\n"
4060  "2. \"transactions\" (string, required) A json array of objects. Each object the txid (string) vout (numeric)\n"
4061  " [ (json array of json objects)\n"
4062  " {\n"
4063  " \"txid\":\"id\", (string) The transaction id\n"
4064  " \"vout\": n (numeric) The output number\n"
4065  " }\n"
4066  " ,...\n"
4067  " ]\n"
4068 
4069  "\nResult:\n"
4070  "true|false (boolean) Whether the command was successful or not\n"
4071 
4072  "\nExamples:\n"
4073  "\nList the unspent transactions\n" +
4074  HelpExampleCli("listunspent", "") +
4075  "\nLock an unspent transaction\n" +
4076  HelpExampleCli("lockunspent", "false true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
4077  "\nList the locked transactions\n" +
4078  HelpExampleCli("listlockunspent", "") +
4079  "\nUnlock the transaction again\n" +
4080  HelpExampleCli("lockunspent", "true true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
4081  "\nAs a json rpc call\n" +
4082  HelpExampleRpc("lockunspent", "false false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\""));
4083 
4084  // Make sure the results are valid at least up to the most recent block
4085  // the user could have gotten from another RPC command prior to now
4086  pwallet->BlockUntilSyncedToCurrentChain();
4087 
4088  LOCK2(cs_main, pwallet->cs_wallet);
4089 
4090  if (request.params.size() == 2)
4091  RPCTypeCheck(request.params, {UniValue::VBOOL, UniValue::VBOOL});
4092  else
4093  RPCTypeCheck(request.params, {UniValue::VBOOL, UniValue::VBOOL, UniValue::VARR});
4094 
4095  bool fUnlock = request.params[0].get_bool();
4096  bool transparent = request.params[1].get_bool();
4097 
4098  if (request.params.size() == 2) {
4099  if (fUnlock) transparent ? pwallet->UnlockAllCoins() : pwallet->UnlockAllNotes();
4100  return true;
4101  }
4102 
4103  UniValue output_request = request.params[2].get_array();
4104 
4105  // Create and validate the COutPoints first.
4106  std::vector<COutPoint> outputs;
4107  std::vector<SaplingOutPoint> saplingOutputs;
4108  transparent ? outputs.reserve(output_request.size()) : saplingOutputs.reserve(output_request.size());
4109 
4110  for (unsigned int idx = 0; idx < output_request.size(); idx++) {
4111  const UniValue& output = output_request[idx];
4112  if (!output.isObject())
4113  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
4114  const UniValue& o = output.get_obj();
4115 
4116  RPCTypeCheckObj(o,
4117  {
4118  {"txid", UniValueType(UniValue::VSTR)},
4119  {"vout", UniValueType(UniValue::VNUM)},
4120  });
4121 
4122  const uint256 txid(ParseHashO(o, "txid"));
4123 
4124  const int nOutput = find_value(o, "vout").get_int();
4125  if (nOutput < 0) {
4126  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
4127  }
4128 
4129  bool is_locked = false;
4130 
4131  const auto it = pwallet->mapWallet.find(txid);
4132  if (it == pwallet->mapWallet.end()) {
4133  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, unknown transaction");
4134  }
4135 
4136  const CWalletTx& wtx = it->second;
4137  if (transparent) {
4138  const COutPoint outpt(txid, nOutput);
4139  if (outpt.n >= wtx.tx->vout.size()) {
4140  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout index out of bounds");
4141  }
4142 
4143  if (pwallet->IsSpent(outpt.hash, outpt.n)) {
4144  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected unspent output");
4145  }
4146  is_locked = pwallet->IsLockedCoin(outpt.hash, outpt.n);
4147  } else {
4148  const SaplingOutPoint op(txid, nOutput);
4149  if (op.n >= wtx.tx->sapData->vShieldedOutput.size()) {
4150  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout index out of bounds");
4151  }
4152  if (pwallet->IsSaplingSpent(op)) {
4153  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected unspent output");
4154  }
4155  is_locked = pwallet->IsLockedNote(op);
4156  }
4157 
4158  if (fUnlock && !is_locked) {
4159  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected locked output");
4160  }
4161 
4162  if (!fUnlock && is_locked) {
4163  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, output already locked");
4164  }
4165 
4166  transparent ? outputs.push_back(COutPoint(txid, nOutput)) : saplingOutputs.push_back(SaplingOutPoint(txid, nOutput));
4167  }
4168 
4169  // Atomically set (un)locked status for the outputs.
4170  for (const COutPoint& outpt : outputs) {
4171  if (fUnlock) pwallet->UnlockCoin(outpt);
4172  else pwallet->LockCoin(outpt);
4173  }
4174 
4175  for (const SaplingOutPoint& op : saplingOutputs) {
4176  if (fUnlock) pwallet->UnlockNote(op);
4177  else
4178  pwallet->LockNote(op);
4179  }
4180 
4181  return true;
4182 }
4183 
4185 {
4186  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
4187 
4188  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
4189  return NullUniValue;
4190 
4191  if (request.fHelp || request.params.size() > 0)
4192  throw std::runtime_error(
4193  "listlockunspent\n"
4194  "\nReturns list of temporarily unspendable outputs.\n"
4195  "See the lockunspent call to lock and unlock transactions for spending.\n"
4196 
4197  "\nResult:\n"
4198  "{\n"
4199  " \"transparent\": [ (array of json objects)\n"
4200  " {\n"
4201  " \"txid\": \"transactionid\" (string) The transaction id locked\n"
4202  " \"vout\": n (numeric) The vout value\n"
4203  " },\n"
4204  " ...\n"
4205  " ],\n"
4206  " \"shielded\": [ (array of json objects)\n"
4207  " {\n"
4208  " \"txid\": \"transactionid\" (string) The transaction id locked\n"
4209  " \"vShieldedOutput\": n (numeric) The vout value\n"
4210  " },\n"
4211  " ...\n"
4212  " ],\n"
4213  "}\n"
4214 
4215  "\nExamples:\n"
4216  "\nList the unspent transactions\n" +
4217  HelpExampleCli("listunspent", "") +
4218  "\nLock an unspent transaction\n" +
4219  HelpExampleCli("lockunspent", "false true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
4220  "\nList the locked transactions\n" +
4221  HelpExampleCli("listlockunspent", "") +
4222  "\nUnlock the transaction again\n" +
4223  HelpExampleCli("lockunspent", "true true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
4224  "\nAs a json rpc call\n" +
4225  HelpExampleRpc("listlockunspent", ""));
4226 
4227  LOCK2(cs_main, pwallet->cs_wallet);
4228 
4229 
4230  UniValue ret(UniValue::VOBJ);
4231  UniValue transparent(UniValue::VARR);
4232  UniValue shielded(UniValue::VARR);
4233 
4234  std::set<COutPoint> vOutpts = pwallet->ListLockedCoins();
4235  for (const COutPoint& outpt : vOutpts) {
4237 
4238  o.pushKV("txid", outpt.hash.GetHex());
4239  o.pushKV("vout", (int)outpt.n);
4240  transparent.push_back(o);
4241  }
4242 
4243  std::set<SaplingOutPoint> sOps = pwallet->ListLockedNotes();
4244  for (const SaplingOutPoint& op : sOps) {
4246 
4247  o.pushKV("txid", op.hash.GetHex());
4248  o.pushKV("vShieldedOutput", (int)op.n);
4249  shielded.push_back(o);
4250  }
4251  ret.pushKV("transparent", transparent);
4252  ret.pushKV("shielded", shielded);
4253  return ret;
4254 }
4255 
4257 {
4258  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
4259 
4260  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
4261  return NullUniValue;
4262 
4263  if (request.fHelp || request.params.size() < 1 || request.params.size() > 1)
4264  throw std::runtime_error(
4265  "settxfee amount\n"
4266  "\nSet the transaction fee per kB.\n"
4267 
4268  "\nArguments:\n"
4269  "1. amount (numeric, required) The transaction fee in PIV/kB rounded to the nearest 0.00000001\n"
4270 
4271  "\nResult\n"
4272  "true|false (boolean) Returns true if successful\n"
4273  "\nExamples:\n" +
4274  HelpExampleCli("settxfee", "0.00001") + HelpExampleRpc("settxfee", "0.00001"));
4275 
4276  LOCK2(cs_main, pwallet->cs_wallet);
4277 
4278  // Amount
4279  CAmount nAmount = 0;
4280  if (request.params[0].get_real() != 0.0)
4281  nAmount = AmountFromValue(request.params[0]); // rejects 0.0 amounts
4282 
4283  payTxFee = CFeeRate(nAmount, 1000);
4284  return true;
4285 }
4286 
4288 {
4289  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
4290 
4291  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
4292  return NullUniValue;
4293 
4294  if (request.fHelp || request.params.size() != 0)
4295  throw std::runtime_error(
4296  "getwalletinfo\n"
4297  "Returns an object containing various wallet state info.\n"
4298 
4299  "\nResult:\n"
4300  "{\n"
4301  " \"walletname\": xxxxx, (string) the wallet name\n"
4302  " \"walletversion\": xxxxx, (numeric) the wallet version\n"
4303  " \"balance\": xxxxxxx, (numeric) the total PIV balance of the wallet (cold balance excluded)\n"
4304  " \"delegated_balance\": xxxxx, (numeric) the PIV balance held in P2CS (cold staking) contracts\n"
4305  " \"cold_staking_balance\": xx, (numeric) the PIV balance held in cold staking addresses\n"
4306  " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in PIV\n"
4307  " \"immature_delegated_balance\": xxxxxx, (numeric) the delegated immature balance of the wallet in PIV\n"
4308  " \"immature_cold_staking_balance\": xxxxxx, (numeric) the cold-staking immature balance of the wallet in PIV\n"
4309  " \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in PIV\n"
4310  " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n"
4311  " \"autocombine_enabled\": true|false, (boolean) true if autocombine is enabled, otherwise false\n"
4312  " \"autocombine_threshold\": x.xxx, (numeric) the current autocombine threshold in PIV\n"
4313  " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
4314  " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated (only counts external keys)\n"
4315  " \"keypoolsize_hd_internal\": xxxx, (numeric) how many new keys are pre-generated for internal use (used for change outputs, only appears if the wallet is using this feature, otherwise external keys are used)\n"
4316  " \"keypoolsize_hd_staking\": xxxx, (numeric) how many new keys are pre-generated for staking use (used for staking contracts, only appears if the wallet is using this feature)\n"
4317  " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
4318  " \"paytxfee\": x.xxxx (numeric) the transaction fee configuration, set in PIV/kB\n"
4319  " \"hdseedid\": \"<hash160>\" (string, optional) the Hash160 of the HD seed (only present when HD is enabled)\n"
4320  " \"last_processed_block\": xxxxx, (numeric) the last block processed block height\n"
4321  "}\n"
4322 
4323  "\nExamples:\n" +
4324  HelpExampleCli("getwalletinfo", "") + HelpExampleRpc("getwalletinfo", ""));
4325 
4326  // Make sure the results are valid at least up to the most recent block
4327  // the user could have gotten from another RPC command prior to now
4328  pwallet->BlockUntilSyncedToCurrentChain();
4329 
4330  LOCK2(cs_main, pwallet->cs_wallet);
4331 
4332  UniValue obj(UniValue::VOBJ);
4333  obj.pushKV("walletname", pwallet->GetName());
4334  obj.pushKV("walletversion", pwallet->GetVersion());
4335  obj.pushKV("balance", ValueFromAmount(pwallet->GetAvailableBalance()));
4336  obj.pushKV("delegated_balance", ValueFromAmount(pwallet->GetDelegatedBalance()));
4337  obj.pushKV("cold_staking_balance", ValueFromAmount(pwallet->GetColdStakingBalance()));
4338  obj.pushKV("unconfirmed_balance", ValueFromAmount(pwallet->GetUnconfirmedBalance()));
4339  obj.pushKV("immature_balance", ValueFromAmount(pwallet->GetImmatureBalance()));
4340  obj.pushKV("immature_delegated_balance", ValueFromAmount(pwallet->GetImmatureDelegatedBalance()));
4341  obj.pushKV("immature_cold_staking_balance", ValueFromAmount(pwallet->GetImmatureColdStakingBalance()));
4342  obj.pushKV("txcount", (int)pwallet->mapWallet.size());
4343 
4344  // Autocombine settings
4345  obj.pushKV("autocombine_enabled", pwallet->fCombineDust);
4346  obj.pushKV("autocombine_threshold", ValueFromAmount(pwallet->nAutoCombineThreshold));
4347  obj.pushKV("autocombine_frequency", pwallet->frequency);
4348 
4349  // Keypool information
4350  obj.pushKV("keypoololdest", pwallet->GetOldestKeyPoolTime());
4351  size_t kpExternalSize = pwallet->KeypoolCountExternalKeys();
4352  obj.pushKV("keypoolsize", (int64_t)kpExternalSize);
4353 
4354  ScriptPubKeyMan* spk_man = pwallet->GetScriptPubKeyMan();
4355  if (spk_man) {
4356  const CKeyID& seed_id = spk_man->GetHDChain().GetID();
4357  if (!seed_id.IsNull()) {
4358  obj.pushKV("hdseedid", seed_id.GetHex());
4359  }
4360  }
4361  if (pwallet->IsHDEnabled()) {
4362  obj.pushKV("keypoolsize_hd_internal", (int64_t)(pwallet->GetKeyPoolSize() - kpExternalSize));
4363  obj.pushKV("keypoolsize_hd_staking", (int64_t)(pwallet->GetStakingKeyPoolSize()));
4364  }
4365 
4366  if (pwallet->IsCrypted())
4367  obj.pushKV("unlocked_until", pwallet->nRelockTime);
4368  obj.pushKV("paytxfee", ValueFromAmount(payTxFee.GetFeePerK()));
4369  obj.pushKV("last_processed_block", pwallet->GetLastBlockHeight());
4370  return obj;
4371 }
4372 
4374 {
4375  if (request.fHelp || !request.params.empty())
4376  throw std::runtime_error(
4377  "listwallets\n"
4378  "Returns a list of currently loaded wallets.\n"
4379  "For full information on the wallet, use \"getwalletinfo\"\n"
4380  "\nResult:\n"
4381  "[ (json array of strings)\n"
4382  " \"walletname\" (string) the wallet name\n"
4383  " ...\n"
4384  "]\n"
4385  "\nExamples:\n"
4386  + HelpExampleCli("listwallets", "")
4387  + HelpExampleRpc("listwallets", "")
4388  );
4389 
4390  UniValue obj(UniValue::VARR);
4391 
4392  for (CWalletRef pwallet : vpwallets) {
4393  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
4394  return NullUniValue;
4395  }
4396 
4397  LOCK(pwallet->cs_wallet);
4398  obj.push_back(pwallet->GetName());
4399  }
4400 
4401  return obj;
4402 }
4403 
4405 {
4406  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
4407 
4408  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
4409  return NullUniValue;
4410 
4411  if (request.fHelp || request.params.size() != 0)
4412  throw std::runtime_error(
4413  "getstakingstatus\n"
4414  "\nReturns an object containing various staking information.\n"
4415 
4416  "\nResult:\n"
4417  "{\n"
4418  " \"staking_status\": true|false, (boolean) whether the wallet is staking or not\n"
4419  " \"staking_enabled\": true|false, (boolean) whether staking is enabled/disabled in pivx.conf\n"
4420  " \"coldstaking_enabled\": true|false, (boolean) whether cold-staking is enabled/disabled in pivx.conf\n"
4421  " \"haveconnections\": true|false, (boolean) whether network connections are present\n"
4422  " \"mnsync\": true|false, (boolean) whether the required masternode/spork data is synced\n"
4423  " \"walletunlocked\": true|false, (boolean) whether the wallet is unlocked\n"
4424  " \"stakeablecoins\": n (numeric) number of stakeable UTXOs\n"
4425  " \"stakingbalance\": d (numeric) PIV value of the stakeable coins (minus reserve balance, if any)\n"
4426  " \"stakesplitthreshold\": d (numeric) value of the current threshold for stake split\n"
4427  " \"lastattempt_age\": n (numeric) seconds since last stake attempt\n"
4428  " \"lastattempt_depth\": n (numeric) depth of the block on top of which the last stake attempt was made\n"
4429  " \"lastattempt_hash\": xxx (hex string) hash of the block on top of which the last stake attempt was made\n"
4430  " \"lastattempt_coins\": n (numeric) number of stakeable coins available during last stake attempt\n"
4431  " \"lastattempt_tries\": n (numeric) number of stakeable coins checked during last stake attempt\n"
4432  "}\n"
4433 
4434  "\nExamples:\n" +
4435  HelpExampleCli("getstakingstatus", "") + HelpExampleRpc("getstakingstatus", ""));
4436 
4437 
4438  if (!pwallet)
4439  throw JSONRPCError(RPC_IN_WARMUP, "Try again after active chain is loaded");
4440  {
4441  LOCK2(cs_main, &pwallet->cs_wallet);
4442  UniValue obj(UniValue::VOBJ);
4443  obj.pushKV("staking_status", pwallet->pStakerStatus->IsActive());
4444  obj.pushKV("staking_enabled", gArgs.GetBoolArg("-staking", DEFAULT_STAKING));
4445  bool fColdStaking = gArgs.GetBoolArg("-coldstaking", true);
4446  obj.pushKV("coldstaking_enabled", fColdStaking);
4447  obj.pushKV("haveconnections", (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) > 0));
4448  obj.pushKV("mnsync", !masternodeSync.NotCompleted());
4449  obj.pushKV("walletunlocked", !pwallet->IsLocked());
4450  std::vector<CStakeableOutput> vCoins;
4451  pwallet->StakeableCoins(&vCoins);
4452  obj.pushKV("stakeablecoins", (int)vCoins.size());
4453  obj.pushKV("stakingbalance", ValueFromAmount(pwallet->GetStakingBalance(fColdStaking)));
4454  obj.pushKV("stakesplitthreshold", ValueFromAmount(pwallet->nStakeSplitThreshold));
4455  CStakerStatus* ss = pwallet->pStakerStatus;
4456  if (ss) {
4457  obj.pushKV("lastattempt_age", (int)(GetTime() - ss->GetLastTime()));
4458  obj.pushKV("lastattempt_depth", (chainActive.Height() - ss->GetLastHeight()));
4459  obj.pushKV("lastattempt_hash", ss->GetLastHash().GetHex());
4460  obj.pushKV("lastattempt_coins", ss->GetLastCoins());
4461  obj.pushKV("lastattempt_tries", ss->GetLastTries());
4462  }
4463  return obj;
4464  }
4465 }
4466 
4468 {
4469  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
4470 
4471  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
4472  return NullUniValue;
4473 
4474  if (request.fHelp || request.params.size() != 1)
4475  throw std::runtime_error(
4476  "setstakesplitthreshold value\n\n"
4477  "This will set the stake-split threshold value.\n"
4478  "Whenever a successful stake is found, the stake amount is split across as many outputs (each with a value\n"
4479  "higher than the threshold) as possible.\n"
4480  "E.g. If the coinstake input + the block reward is 2000, and the split threshold is 499, the corresponding\n"
4481  "coinstake transaction will have 4 outputs (of 500 PIV each)."
4482  + HelpRequiringPassphrase(pwallet) + "\n"
4483 
4484  "\nArguments:\n"
4485  "1. value (numeric, required) Threshold value (in PIV).\n"
4486  " Set to 0 to disable stake-splitting\n"
4487  " If > 0, it must be >= " + FormatMoney(CWallet::minStakeSplitThreshold) + "\n"
4488 
4489  "\nResult:\n"
4490  "{\n"
4491  " \"threshold\": n, (numeric) Threshold value set\n"
4492  " \"saved\": true|false (boolean) 'true' if successfully saved to the wallet file\n"
4493  "}\n"
4494 
4495  "\nExamples:\n" +
4496  HelpExampleCli("setstakesplitthreshold", "500.12") + HelpExampleRpc("setstakesplitthreshold", "500.12"));
4497 
4498  CAmount nStakeSplitThreshold = AmountFromValue(request.params[0]);
4499  if (nStakeSplitThreshold > 0 && nStakeSplitThreshold < CWallet::minStakeSplitThreshold)
4500  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf(_("The threshold value cannot be less than %s"),
4502 
4503  UniValue result(UniValue::VOBJ);
4504  result.pushKV("threshold", request.params[0]);
4505  result.pushKV("saved", pwallet->SetStakeSplitThreshold(nStakeSplitThreshold));
4506  return result;
4507 }
4508 
4510 {
4511  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
4512 
4513  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
4514  return NullUniValue;
4515 
4516  if (request.fHelp || request.params.size() != 0)
4517  throw std::runtime_error(
4518  "getstakesplitthreshold\n"
4519  "Returns the threshold for stake splitting\n"
4520 
4521  "\nResult:\n"
4522  "n (numeric) Threshold value\n"
4523 
4524  "\nExamples:\n" +
4525  HelpExampleCli("getstakesplitthreshold", "") + HelpExampleRpc("getstakesplitthreshold", ""));
4526 
4527  return ValueFromAmount(pwallet->GetStakeSplitThreshold());
4528 }
4529 
4531 {
4532  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
4533 
4534  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
4535  return NullUniValue;
4536 
4537  if (request.fHelp || request.params.empty() || request.params.size() > 3)
4538  throw std::runtime_error(
4539  "setautocombinethreshold enable ( value )\n"
4540  "\nThis will set the auto-combine threshold value.\n"
4541  "\nWallet will automatically monitor for any coins with value below the threshold amount, and combine them if they reside with the same PIVX address\n"
4542  "When auto-combine runs it will create a transaction, and therefore will be subject to transaction fees.\n"
4543 
4544  "\nArguments:\n"
4545  "1. enable (boolean, required) Enable auto combine (true) or disable (false).\n"
4546  "2. threshold (numeric, optional. required if enable is true) Threshold amount. Must be greater than 1.\n"
4547  "3. frequency (numeric, optional. default value is 30 if not provided). Check for UTXOs to autocombine each N blocks where N is the frequency.\n"
4548 
4549  "\nResult:\n"
4550  "{\n"
4551  " \"enabled\": true|false, (boolean) true if auto-combine is enabled, otherwise false\n"
4552  " \"threshold\": n.nnn, (numeric) auto-combine threshold in PIV\n"
4553  " \"frequency\": n.nnn, (numeric) auto-combine frequency in blocks\n"
4554  " \"saved\": true|false (boolean) true if setting was saved to the database, otherwise false\n"
4555  "}\n"
4556 
4557  "\nExamples:\n" +
4558  HelpExampleCli("setautocombinethreshold", "true 500.12 40") + HelpExampleRpc("setautocombinethreshold", "true, 500.12, 40"));
4559 
4560  RPCTypeCheck(request.params, {UniValue::VBOOL, UniValue::VNUM, UniValue::VNUM});
4561 
4562  bool fEnable = request.params[0].get_bool();
4563  CAmount nThreshold = 0;
4564  int frequency = 30;
4565 
4566  if (fEnable) {
4567  if (request.params.size() < 2) {
4568  throw JSONRPCError(RPC_INVALID_PARAMETER, "Missing threshold value");
4569  }
4570  nThreshold = AmountFromValue(request.params[1]);
4571  if (nThreshold < COIN)
4572  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("The threshold value cannot be less than %s", FormatMoney(COIN)));
4573  if (request.params.size() == 3) {
4574  frequency = request.params[2].get_int();
4575  if (frequency <= 0) {
4576  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Frequency must be greater than 0"));
4577  }
4578  }
4579  }
4580 
4581  WalletBatch batch(pwallet->GetDBHandle());
4582 
4583  {
4584  LOCK(pwallet->cs_wallet);
4585  pwallet->fCombineDust = fEnable;
4586  pwallet->nAutoCombineThreshold = nThreshold;
4587  pwallet->frequency = frequency;
4588 
4589  UniValue result(UniValue::VOBJ);
4590  result.pushKV("enabled", fEnable);
4591  result.pushKV("threshold", ValueFromAmount(pwallet->nAutoCombineThreshold));
4592  result.pushKV("frequency", frequency);
4593  if (batch.WriteAutoCombineSettings(fEnable, nThreshold, frequency)) {
4594  result.pushKV("saved", "true");
4595  } else {
4596  result.pushKV("saved", "false");
4597  }
4598 
4599  return result;
4600  }
4601 }
4602 
4604 {
4605  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
4606 
4607  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
4608  return NullUniValue;
4609 
4610  if (request.fHelp || !request.params.empty())
4611  throw std::runtime_error(
4612  "getautocombinethreshold\n"
4613  "\nReturns the current threshold and frequency for auto combining UTXOs, if any\n"
4614 
4615  "\nResult:\n"
4616  "{\n"
4617  " \"enabled\": true|false, (boolean) true if auto-combine is enabled, otherwise false\n"
4618  " \"threshold\": n.nnn (numeric) the auto-combine threshold amount in PIV\n"
4619  " \"frequency\": n.nnn (numeric) the auto-combine frequency in blocks\n"
4620  "}\n"
4621 
4622  "\nExamples:\n" +
4623  HelpExampleCli("getautocombinethreshold", "") + HelpExampleRpc("getautocombinethreshold", ""));
4624 
4625  LOCK(pwallet->cs_wallet);
4626 
4627  UniValue result(UniValue::VOBJ);
4628  result.pushKV("enabled", pwallet->fCombineDust);
4629  result.pushKV("threshold", ValueFromAmount(pwallet->nAutoCombineThreshold));
4630  result.pushKV("frequency", pwallet->frequency);
4631 
4632  return result;
4633 }
4634 
4636 {
4637  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
4638 
4639  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
4640  return NullUniValue;
4641 
4642  if (request.fHelp || request.params.size() > 1)
4643  throw std::runtime_error(
4644  "getsaplingnotescount ( minconf )\n"
4645  "Returns the number of sapling notes available in the wallet.\n"
4646 
4647  "\nArguments:\n"
4648  "1. minconf (numeric, optional, default=1) Only include notes in transactions confirmed at least this many times.\n"
4649 
4650  "\nResult:\n"
4651  "num (numeric) the number of sapling notes in the wallet\n"
4652 
4653  "\nExamples:\n"
4654  + HelpExampleCli("getsaplingnotescount", "0")
4655  + HelpExampleRpc("getsaplingnotescount", "0")
4656  );
4657 
4658  // Make sure the results are valid at least up to the most recent block
4659  // the user could have gotten from another RPC command prior to now
4660  pwallet->BlockUntilSyncedToCurrentChain();
4661 
4662  LOCK2(cs_main, pwallet->cs_wallet);
4663 
4664  int nMinDepth = !request.params.empty() ? request.params[0].get_int() : 1;
4665  int count = 0;
4666  for (const auto& wtx : pwallet->mapWallet) {
4667  if (wtx.second.GetDepthInMainChain() >= nMinDepth) {
4668  for (const auto& nd : wtx.second.mapSaplingNoteData) {
4669  if (nd.second.IsMyNote()) count++;
4670  }
4671  }
4672  }
4673  return count;
4674 }
4675 
4677 {
4678  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
4679 
4680  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
4681  return NullUniValue;
4682 
4683  if (request.fHelp || request.params.size() > 2) {
4684  throw std::runtime_error(
4685  "rescanblockchain (start_height) (stop_height)\n"
4686  "\nRescan the local blockchain for wallet related transactions.\n"
4687  "\nArguments:\n"
4688  "1. start_height (numeric, optional) block height where the rescan should start\n"
4689  "2. stop_height (numeric, optional) the last block height that should be scanned\n"
4690  "\nResult:\n"
4691  "{\n"
4692  " start_height (numeric) The block height where the rescan has started. If omitted, rescan started from the genesis block.\n"
4693  " stop_height (numeric) The height of the last rescanned block. If omitted, rescan stopped at the chain tip.\n"
4694  "}\n"
4695  "\nExamples:\n"
4696  + HelpExampleCli("rescanblockchain", "100000 120000")
4697  + HelpExampleRpc("rescanblockchain", "100000 120000")
4698  );
4699  }
4700 
4701  WalletRescanReserver reserver(pwallet);
4702  if (!reserver.reserve()) {
4703  throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
4704  }
4705 
4706  CBlockIndex *pindexStart = nullptr;
4707  CBlockIndex *pindexStop = nullptr;
4708  CBlockIndex *pChainTip = nullptr;
4709  {
4710  LOCK(cs_main);
4711  pindexStart = chainActive.Genesis();
4712  pChainTip = chainActive.Tip();
4713 
4714  if (!request.params[0].isNull()) {
4715  pindexStart = chainActive[request.params[0].get_int()];
4716  if (!pindexStart) {
4717  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid start_height");
4718  }
4719  }
4720 
4721  if (!request.params[1].isNull()) {
4722  pindexStop = chainActive[request.params[1].get_int()];
4723  if (!pindexStop) {
4724  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid stop_height");
4725  }
4726  else if (pindexStop->nHeight < pindexStart->nHeight) {
4727  throw JSONRPCError(RPC_INVALID_PARAMETER, "stop_height must be greater then start_height");
4728  }
4729  }
4730  }
4731 
4732  CBlockIndex *stopBlock = pwallet->ScanForWalletTransactions(pindexStart, pindexStop, reserver, true);
4733  if (!stopBlock) {
4734  if (pwallet->IsAbortingRescan()) {
4735  throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted.");
4736  }
4737  // if we got a nullptr returned, ScanForWalletTransactions did rescan up to the requested stopindex
4738  stopBlock = pindexStop ? pindexStop : pChainTip;
4739  }
4740  else {
4741  throw JSONRPCError(RPC_MISC_ERROR, "Rescan failed. Potentially corrupted data files.");
4742  }
4743 
4744  UniValue response(UniValue::VOBJ);
4745  response.pushKV("start_height", pindexStart->nHeight);
4746  response.pushKV("stop_height", stopBlock->nHeight);
4747  return response;
4748 }
4749 
4750 extern UniValue abortrescan(const JSONRPCRequest& request); // in rpcdump.cpp
4751 extern UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp
4752 extern UniValue importprivkey(const JSONRPCRequest& request);
4753 extern UniValue importaddress(const JSONRPCRequest& request);
4754 extern UniValue importpubkey(const JSONRPCRequest& request);
4755 extern UniValue dumpwallet(const JSONRPCRequest& request);
4756 extern UniValue importwallet(const JSONRPCRequest& request);
4757 extern UniValue importmulti(const JSONRPCRequest& request);
4758 extern UniValue bip38encrypt(const JSONRPCRequest& request);
4759 extern UniValue bip38decrypt(const JSONRPCRequest& request);
4760 
4761 extern UniValue exportsaplingkey(const JSONRPCRequest& request);
4762 extern UniValue importsaplingkey(const JSONRPCRequest& request);
4763 extern UniValue importsaplingviewingkey(const JSONRPCRequest& request);
4764 extern UniValue exportsaplingviewingkey(const JSONRPCRequest& request);
4765 
4766 // clang-format off
4767 static const CRPCCommand commands[] =
4768 { // category name actor (function) okSafe argNames
4769  // --------------------- ------------------------ ----------------------- ------ --------
4770  { "wallet", "getaddressinfo", &getaddressinfo, true, {"address"} },
4771  { "wallet", "setautocombinethreshold", &setautocombinethreshold, false, {"enable","threshold"} },
4772  { "wallet", "getautocombinethreshold", &getautocombinethreshold, false, {} },
4773  { "wallet", "abandontransaction", &abandontransaction, false, {"txid"} },
4774  { "wallet", "abortrescan", &abortrescan, false, {} },
4775  { "wallet", "addmultisigaddress", &addmultisigaddress, true, {"nrequired","keys","label"} },
4776  { "wallet", "backupwallet", &backupwallet, true, {"destination"} },
4777  { "wallet", "delegatestake", &delegatestake, false, {"staking_addr","amount","owner_addr","ext_owner","include_delegated","from_shield","force"} },
4778  { "wallet", "dumpprivkey", &dumpprivkey, true, {"address"} },
4779  { "wallet", "dumpwallet", &dumpwallet, true, {"filename"} },
4780  { "wallet", "encryptwallet", &encryptwallet, true, {"passphrase"} },
4781  { "wallet", "fundrawtransaction", &fundrawtransaction, false, {"hexstring","options"} },
4782  { "wallet", "getbalance", &getbalance, false, {"minconf","include_watchonly","include_delegated","include_shield"} },
4783  { "wallet", "getcoldstakingbalance", &getcoldstakingbalance, false, {} },
4784  { "wallet", "getdelegatedbalance", &getdelegatedbalance, false, {} },
4785  { "wallet", "upgradewallet", &upgradewallet, true, {} },
4786  { "wallet", "sethdseed", &sethdseed, true, {"newkeypool","seed"} },
4787  { "wallet", "getnewaddress", &getnewaddress, true, {"label"} },
4788  { "wallet", "getnewexchangeaddress", &getnewexchangeaddress, true, {"label"} },
4789  { "wallet", "getnewstakingaddress", &getnewstakingaddress, true, {"label"} },
4790  { "wallet", "getrawchangeaddress", &getrawchangeaddress, true, {} },
4791  { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, false, {"address","minconf"} },
4792  { "wallet", "gettransaction", &gettransaction, false, {"txid","include_watchonly"} },
4793  { "wallet", "getstakesplitthreshold", &getstakesplitthreshold, false, {} },
4794  { "wallet", "getunconfirmedbalance", &getunconfirmedbalance, false, {} },
4795  { "wallet", "getwalletinfo", &getwalletinfo, false, {} },
4796  { "wallet", "getstakingstatus", &getstakingstatus, false, {} },
4797  { "wallet", "importprivkey", &importprivkey, true, {"privkey","label","rescan","is_staking_address"} },
4798  { "wallet", "importwallet", &importwallet, true, {"filename"} },
4799  { "wallet", "importaddress", &importaddress, true, {"address","label","rescan","p2sh"} },
4800  { "wallet", "importpubkey", &importpubkey, true, {"pubkey","label","rescan"} },
4801  { "wallet", "importmulti", &importmulti, true, {"requests","options"} },
4802  { "wallet", "keypoolrefill", &keypoolrefill, true, {"newsize"} },
4803  { "wallet", "listaddressgroupings", &listaddressgroupings, false, {} },
4804  { "wallet", "listdelegators", &listdelegators, false, {"blacklist"} },
4805  { "wallet", "liststakingaddresses", &liststakingaddresses, false, {} },
4806  { "wallet", "listcoldutxos", &listcoldutxos, false, {"not_whitelisted"} },
4807  { "wallet", "listlockunspent", &listlockunspent, false, {} },
4808  { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false, {"minconf","include_empty","include_watchonly","filter"} },
4809  { "wallet", "listsinceblock", &listsinceblock, false, {"blockhash","target_confirmations","include_watchonly"} },
4810  { "wallet", "listtransactions", &listtransactions, false, {"dummy","count","from","include_watchonly","include_delegated","include_cold"} },
4811  { "wallet", "listunspent", &listunspent, false, {"minconf","maxconf","addresses","watchonly_config","query_options","include_unsafe" } },
4812  { "wallet", "listwallets", &listwallets, true, {} },
4813  { "wallet", "lockunspent", &lockunspent, true, {"unlock", "transparent", "transactions"} },
4814  { "wallet", "rawdelegatestake", &rawdelegatestake, false, {"staking_addr","amount","owner_addr","ext_owner","include_delegated","from_shield","force"} },
4815  { "wallet", "sendmany", &sendmany, false, {"dummy","amounts","minconf","comment","include_delegated","subtract_fee_from"} },
4816  { "wallet", "sendtoaddress", &sendtoaddress, false, {"address","amount","comment","comment-to","subtract_fee"} },
4817  { "wallet", "settxfee", &settxfee, true, {"amount"} },
4818  { "wallet", "setstakesplitthreshold", &setstakesplitthreshold, false, {"value"} },
4819  { "wallet", "signmessage", &signmessage, true, {"address","message"} },
4820  { "wallet", "walletlock", &walletlock, true, {} },
4821  { "wallet", "walletpassphrasechange", &walletpassphrasechange, true, {"oldpassphrase","newpassphrase"} },
4822  { "wallet", "walletpassphrase", &walletpassphrase, true, {"passphrase","timeout","staking_only"} },
4823  { "wallet", "rescanblockchain", &rescanblockchain, true, {"start_height","stop_height"} },
4824  { "wallet", "delegatoradd", &delegatoradd, true, {"address","label"} },
4825  { "wallet", "delegatorremove", &delegatorremove, true, {"address"} },
4826  { "wallet", "bip38encrypt", &bip38encrypt, true, {"address","passphrase"} },
4827  { "wallet", "bip38decrypt", &bip38decrypt, true, {"encrypted_key","passphrase"} },
4828 
4830  { "wallet", "getnewshieldaddress", &getnewshieldaddress, true, {"label"} },
4831  { "wallet", "listshieldaddresses", &listshieldaddresses, false, {"include_watchonly"} },
4832  { "wallet", "exportsaplingkey", &exportsaplingkey, true, {"shield_addr"} },
4833  { "wallet", "importsaplingkey", &importsaplingkey, true, {"key","rescan","height"} },
4834  { "wallet", "importsaplingviewingkey", &importsaplingviewingkey, true, {"vkey","rescan","height"} },
4835  { "wallet", "exportsaplingviewingkey", &exportsaplingviewingkey, true, {"shield_addr"} },
4836  { "wallet", "getshieldbalance", &getshieldbalance, false, {"address","minconf","include_watchonly"} },
4837  { "wallet", "listshieldunspent", &listshieldunspent, false, {"minconf","maxconf","include_watchonly","addresses"} },
4838  { "wallet", "rawshieldsendmany", &rawshieldsendmany, false, {"fromaddress","amounts","minconf","fee"} },
4839  { "wallet", "shieldsendmany", &shieldsendmany, false, {"fromaddress","amounts","minconf","fee","subtract_fee_from"} },
4840  { "wallet", "listreceivedbyshieldaddress", &listreceivedbyshieldaddress, false, {"address","minconf"} },
4841  { "wallet", "viewshieldtransaction", &viewshieldtransaction, false, {"txid"} },
4842  { "wallet", "getsaplingnotescount", &getsaplingnotescount, false, {"minconf"} },
4843 
4845  { "wallet", "getaddressesbylabel", &getaddressesbylabel, true, {"label"} },
4846  { "wallet", "getreceivedbylabel", &getreceivedbylabel, false, {"label","minconf"} },
4847  { "wallet", "listlabels", &listlabels, false, {"purpose"} },
4848  { "wallet", "listreceivedbylabel", &listreceivedbylabel, false, {"minconf","include_empty","include_watchonly"} },
4849  { "wallet", "setlabel", &setlabel, true, {"address","label"} },
4850 };
4851 // clang-format on
4852 
4854 {
4855  if (gArgs.GetBoolArg("-disablewallet", false)) {
4856  return;
4857  }
4858  for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) {
4859  tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
4860  }
4861 }
bool IsValidPaymentAddress(const libzcash::PaymentAddress &zaddr)
Check whether a PaymentAddress is not an InvalidEncoding.
Definition: address.cpp:92
int64_t CAmount
Amount in PIV (Can be negative)
Definition: amount.h:13
const CChainParams & Params()
Return the currently selected parameters.
Address book data.
Definition: addressbook.h:31
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: system.cpp:465
uint256 hash
Definition: transaction.h:35
uint32_t n
Definition: transaction.h:36
void SetFilter(CTxDestination &filter)
Definition: wallet.h:255
void GetSaplingPaymentAddresses(std::set< libzcash::SaplingPaymentAddress > &setAddress) const
Definition: keystore.cpp:252
virtual bool GetCScript(const CScriptID &hash, CScript &redeemScriptOut) const
Definition: keystore.cpp:57
bool GetSaplingExtendedSpendingKey(const libzcash::SaplingPaymentAddress &addr, libzcash::SaplingExtendedSpendingKey &extskOut) const
Definition: keystore.cpp:240
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:139
uint256 GetBlockHash() const
Definition: chain.h:215
int64_t GetBlockTime() const
Definition: chain.h:216
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:151
CBlockIndex * Genesis() const
Returns the index entry for the genesis block of this chain, or nullptr if none.
Definition: chain.h:399
CBlockIndex * Tip(bool fProofOfStake=false) const
Returns the index entry for the tip of this chain, or nullptr if none.
Definition: chain.h:405
int Height() const
Return the maximal height in the chain.
Definition: chain.h:450
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:72
Coin Control Features.
Definition: coincontrol.h:34
bool fAllowWatchOnly
Includes watch only addresses which are solvable.
Definition: coincontrol.h:42
@ CONNECTIONS_ALL
Definition: net.h:152
bool GetKey(const CKeyID &address, CKey &keyOut) const override
Definition: crypter.cpp:199
bool IsLocked() const
Definition: crypter.cpp:148
bool HaveKey(const CKeyID &address) const override
Check whether a key corresponding to a given address is present in the store.
Definition: crypter.cpp:179
bool IsCrypted() const
Definition: crypter.h:154
Fee rate in PIV per kilobyte: CAmount / kB.
Definition: feerate.h:20
CAmount GetFeePerK() const
Definition: feerate.h:29
CKeyID GetID() const
Definition: hdchain.h:52
An encapsulated private key.
Definition: key.h:30
const unsigned char * end() const
Definition: key.h:92
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:95
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
Definition: key.h:98
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:186
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:76
const unsigned char * begin() const
Definition: key.h:91
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:21
KeyOriginInfo key_origin
Definition: walletdb.h:71
bool HasKeyOrigin() const
Definition: walletdb.h:100
int64_t nCreateTime
Definition: walletdb.h:69
CKeyID hd_seed_id
Definition: walletdb.h:70
static bool SignMessage(const std::string &strMessage, std::vector< unsigned char > &vchSigRet, const CKey &key)
Sign the message, returns true if successful.
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:72
An encapsulated public key.
Definition: pubkey.h:44
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:167
PIVX RPC command dispatcher.
Definition: server.h:147
bool appendCommand(const std::string &name, const CRPCCommand *pcmd)
Appends a CRPCCommand to the dispatch table.
Definition: server.cpp:314
A key allocated from the key pool.
Definition: wallet.h:1256
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:381
bool IsPayToScriptHash() const
Definition: script.cpp:223
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:24
bool IsSporkActive(SporkId nSporkID)
Definition: spork.cpp:220
Record info about last stake attempt:
Definition: wallet.h:185
int64_t GetLastTime() const
Definition: wallet.h:199
uint256 GetLastHash() const
Definition: wallet.h:195
int GetLastHeight() const
Definition: wallet.h:196
bool IsActive() const
Definition: wallet.h:213
int GetLastTries() const
Definition: wallet.h:198
int GetLastCoins() const
Definition: wallet.h:197
The basic transaction that is broadcasted on the network and contained in blocks.
Definition: transaction.h:244
An output of a transaction.
Definition: transaction.h:137
CScript scriptPubKey
Definition: transaction.h:140
CAmount nValue
Definition: transaction.h:139
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,...
Definition: wallet.h:577
std::map< uint256, CWalletTx > mapWallet
Definition: wallet.h:766
TxItems wtxOrdered
Definition: wallet.h:769
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
Definition: wallet.h:756
CStakerStatus * pStakerStatus
Definition: wallet.h:737
RecursiveMutex cs_wallet
Definition: wallet.h:720
bool fCombineDust
Definition: wallet.h:744
int GetVersion()
get the current wallet format (the oldest client version guaranteed to understand this wallet)
Definition: wallet.cpp:4701
CAddressBookIterator NewAddressBookIterator()
Definition: wallet.h:1178
int64_t nRelockTime
Lock Wallet Holds a timestamp at which point the wallet is scheduled (externally) to be relocked.
Definition: wallet.h:1009
bool IsAbortingRescan()
Definition: wallet.h:886
CAmount nStakeSplitThreshold
Definition: wallet.h:733
static CAmount minStakeSplitThreshold
minimum accpeted value for stake split threshold
Definition: wallet.h:735
int GetLastBlockHeight() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get last block processed height.
Definition: wallet.h:689
bool BackupWallet(const std::string &strDest)
Creates a wallet backup in strDest path.
Definition: wallet.cpp:4457
bool CanSupportFeature(enum WalletFeature wf)
check whether we are allowed to upgrade (or already support) to the named feature
Definition: wallet.cpp:4584
CAmount nAutoCombineThreshold
Definition: wallet.h:745
bool HaveSpendingKeyForPaymentAddress(const libzcash::SaplingPaymentAddress &zaddr) const
Returns true if the wallet contains the spending key.
Definition: wallet.cpp:4738
unsigned int GetKeyPoolSize()
Definition: wallet.cpp:4691
std::multimap< int64_t, CWalletTx * > TxItems
Definition: wallet.h:768
bool fWalletUnlockStaking
Definition: wallet.h:722
SaplingScriptPubKeyMan * GetSaplingScriptPubKeyMan() const
Definition: wallet.h:712
std::map< CKeyID, CKeyMetadata > mapKeyMetadata
Definition: wallet.h:726
unsigned int GetStakingKeyPoolSize()
Definition: wallet.cpp:4696
libzcash::SaplingPaymentAddress GenerateNewSaplingZKey(std::string label="")
Generates new Sapling key.
Definition: wallet.cpp:4710
CAmount GetStakeSplitThreshold() const
Definition: wallet.h:893
int frequency
Definition: wallet.h:746
WalletDatabase & GetDBHandle() const
Definition: wallet.h:752
A transaction with a bunch of additional info that only the owner cares about.
Definition: wallet.h:325
mapValue_t mapValue
Definition: wallet.h:335
CTransactionRef tx
Definition: wallet.h:364
int GetDepthInMainChain() const NO_THREAD_SAFETY_ANALYSIS
Return depth of transaction in blockchain: <0 : conflicts with a transaction this deep in the blockch...
Definition: wallet.cpp:4477
bool IsFromMe(const isminefilter &filter) const
Definition: wallet.cpp:4949
bool IsCoinStake() const
Definition: wallet.h:563
int GetBlocksToMaturity() const
Definition: wallet.cpp:4486
bool IsTrusted() const
Definition: wallet.cpp:4777
Confirmation m_confirm
Definition: wallet.h:394
mapSaplingNoteData_t mapSaplingNoteData
Definition: wallet.h:336
const uint256 & GetHash() const
Definition: wallet.h:561
bool IsCoinBase() const
Definition: wallet.h:562
unsigned int nTimeReceived
Definition: wallet.h:339
UniValue params
Definition: server.h:47
std::string URI
Definition: server.h:49
bool fHelp
Definition: server.h:48
std::string getError() const
CTransaction getFinalTx()
SaplingOperation * setSelectShieldedCoins(const bool select)
void setFromAddress(const CTxDestination &)
OperationResult send(std::string &retTxHash)
SaplingOperation * setRecipients(std::vector< SendManyRecipient > &vec)
SaplingOperation * setMinDepth(int _mindepth)
OperationResult build()
SaplingOperation * setFee(CAmount _fee)
SaplingOperation * setSelectTransparentCoins(const bool select, const bool _fIncludeDelegated=false)
An outpoint - a combination of a transaction hash and an index n into its sapling output description ...
Definition: transaction.h:82
std::map< libzcash::SaplingIncomingViewingKey, CKeyMetadata > mapSaplingZKeyMetadata
bool IsNoteSaplingChange(const std::set< std::pair< libzcash::PaymentAddress, uint256 >> &nullifierSet, const libzcash::PaymentAddress &address, const SaplingOutPoint &entry) const
std::set< std::pair< libzcash::PaymentAddress, uint256 > > GetNullifiersForAddresses(const std::set< libzcash::PaymentAddress > &addresses) const
void SetHDSeed(const CPubKey &key, bool force=false, bool memonly=false)
void GetFilteredNotes(std::vector< SaplingNoteEntry > &saplingEntries, Optional< libzcash::SaplingPaymentAddress > &address, int minDepth=1, bool ignoreSpent=true, bool requireSpendingKey=true, bool ignoreLocked=true) const
Find notes in the wallet filtered by payment address, min depth and ability to spend and if the notes...
const CHDChain & GetHDChain() const
CPubKey DeriveNewSeed(const CKey &key)
bool NewKeyPool()
Key pool.
void SetHDSeed(const CPubKey &key, bool force=false, bool memOnly=false)
CPubKey GenerateNewSeed()
bool setArray()
Definition: univalue.cpp:94
const std::string & get_str() const
@ VOBJ
Definition: univalue.h:21
@ VSTR
Definition: univalue.h:21
@ VARR
Definition: univalue.h:21
@ VNUM
Definition: univalue.h:21
@ VBOOL
Definition: univalue.h:21
int64_t get_int64() const
bool isNull() const
Definition: univalue.h:77
void clear()
Definition: univalue.cpp:15
const UniValue & get_obj() const
size_t size() const
Definition: univalue.h:68
const std::vector< UniValue > & getValues() const
const std::vector< std::string > & getKeys() const
bool empty() const
Definition: univalue.h:66
bool push_back(const UniValue &val)
Definition: univalue.cpp:108
const UniValue & get_array() const
bool exists(const std::string &key) const
Definition: univalue.h:75
bool pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:133
bool push_backV(const std::vector< UniValue > &vec)
Definition: univalue.cpp:117
double get_real() const
bool get_bool() const
bool isObject() const
Definition: univalue.h:84
int get_int() const
Access to the wallet database.
Definition: walletdb.h:112
bool WriteAutoCombineSettings(bool fEnable, CAmount nCombineThreshold, int frequency)
Definition: walletdb.cpp:245
RAII object to check and reserve a wallet rescan.
Definition: wallet.h:1324
bool IsNull() const
Definition: uint256.h:36
std::string GetHex() const
Definition: uint256.cpp:21
SaplingFullViewingKey full_viewing_key() const
Definition: address.cpp:29
SaplingIncomingViewingKey in_viewing_key() const
Definition: address.cpp:45
Sapling functions.
Definition: address.h:30
void push_back(const T &value)
Definition: prevector.h:435
256-bit opaque blob.
Definition: uint256.h:138
std::string EncodeHexTx(const CTransaction &tx)
Definition: core_write.cpp:116
bool DecodeHexTx(CMutableTransaction &tx, const std::string &strHexTx)
Definition: core_read.cpp:77
boost::variant< CTxDestination, libzcash::SaplingPaymentAddress > CWDestination
const std::string CURRENCY_UNIT
Definition: feerate.cpp:11
void UnlockCoin(const COutPoint &output)
Definition: wallet.cpp:3960
CAmount GetImmatureDelegatedBalance() const
Definition: wallet.cpp:2280
int64_t GetOldestKeyPoolTime()
Definition: wallet.cpp:3757
CAmount GetDelegatedBalance() const
Definition: wallet.cpp:2210
void UnlockAllNotes()
Definition: wallet.cpp:3978
CAmount GetLegacyBalance(const isminefilter &filter, int minDepth) const
Definition: wallet.cpp:2316
void LockNote(const SaplingOutPoint &op)
Definition: wallet.cpp:3954
void KeepKey()
Definition: wallet.cpp:3932
CWallet::CommitResult CommitTransaction(CTransactionRef tx, CReserveKey &opReservekey, CConnman *connman)
Definition: wallet.cpp:3510
size_t KeypoolCountExternalKeys()
Definition: wallet.cpp:3729
CAmount GetImmatureColdStakingBalance() const
Definition: wallet.cpp:2273
CAmount GetColdStakingBalance() const
Definition: wallet.cpp:2188
bool CreateTransaction(const std::vector< CRecipient > &vecSend, CTransactionRef &txRet, CReserveKey &reservekey, CAmount &nFeeRet, int &nChangePosInOut, std::string &strFailReason, const CCoinControl *coinControl=nullptr, bool sign=true, CAmount nFeePay=0, bool fIncludeDelegated=false, bool *fStakeDelegationVoided=nullptr, int nExtraSize=0, int nMinDepth=0)
Create a new transaction paying the recipients with a set of coins selected by SelectCoins(); Also cr...
Definition: wallet.cpp:3040
std::set< std::set< CTxDestination > > GetAddressGroupings()
Definition: wallet.cpp:3804
CAmount GetImmatureBalance() const
Definition: wallet.cpp:2266
bool IsLockedNote(const SaplingOutPoint &op) const
Definition: wallet.cpp:3992
std::set< SaplingOutPoint > ListLockedNotes()
Definition: wallet.cpp:4004
CAmount GetStakingBalance(const bool fIncludeColdStaking=true) const
Definition: wallet.cpp:2196
bool FundTransaction(CMutableTransaction &tx, CAmount &nFeeRet, bool overrideEstimatedFeeRate, const CFeeRate &specificFeeRate, int &nChangePosInOut, std::string &strFailReason, bool includeWatching, bool lockUnspents, const std::set< int > &setSubtractFeeFromOutputs, const CTxDestination &destChange=CNoDestination())
Definition: wallet.cpp:2965
bool AvailableCoins(std::vector< COutput > *pCoins, const CCoinControl *coinControl=nullptr, AvailableCoinsFilter coinsFilter=AvailableCoinsFilter()) const
populate vCoins with vector of available COutputs.
Definition: wallet.cpp:2555
bool SetStakeSplitThreshold(const CAmount sst)
Definition: wallet.cpp:4010
bool TopUpKeyPool(unsigned int kpSize=0)
Definition: wallet.cpp:3734
std::string GetNameForAddressBookEntry(const CWDestination &address) const
Definition: wallet.cpp:3686
void UnlockAllCoins()
Definition: wallet.cpp:3972
bool HasAddressBook(const CWDestination &address) const
Definition: wallet.cpp:3710
CAmount GetAvailableBalance(bool fIncludeDelegated=true, bool fIncludeShielded=true) const
Definition: wallet.cpp:2162
std::set< COutPoint > ListLockedCoins()
Definition: wallet.cpp:3998
bool SetAddressBook(const CWDestination &address, const std::string &strName, const std::string &purpose)
Definition: wallet.cpp:3642
bool IsLockedCoin(const uint256 &hash, unsigned int n) const
Definition: wallet.cpp:3984
bool GetReservedKey(CPubKey &pubkey, bool internal=false)
Definition: wallet.cpp:3901
CAmount GetUnconfirmedBalance(isminetype filter=ISMINE_SPENDABLE_ALL) const
Definition: wallet.cpp:2258
std::string ToString() const
Definition: wallet.cpp:3489
void LockCoin(const COutPoint &output)
Definition: wallet.cpp:3948
std::map< CTxDestination, CAmount > GetAddressBalances()
Definition: wallet.cpp:3762
bool StakeableCoins(std::vector< CStakeableOutput > *pCoins=nullptr)
Available coins (staking)
Definition: wallet.cpp:2709
Optional< AddressBook::CAddressBookData > GetAddressBookEntry(const CWDestination &address) const
Definition: wallet.cpp:3693
std::set< CTxDestination > GetLabelAddresses(const std::string &label) const
Definition: wallet.cpp:3887
void UnlockNote(const SaplingOutPoint &op)
Definition: wallet.cpp:3966
bool IsSaplingSpent(const SaplingOutPoint &op) const
Definition: wallet.cpp:711
bool Lock()
Definition: wallet.cpp:397
CallResult< CTxDestination > getNewAddress(const std::string &addressLabel, const std::string purpose, const CChainParams::Base58Type addrType=CChainParams::PUBKEY_ADDRESS)
Definition: wallet.cpp:196
bool AddCScript(const CScript &redeemScript) override
Support for BIP 0013 : see https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki.
Definition: wallet.cpp:327
bool SetMaxVersion(int nVersion)
change which version we're allowed to upgrade to (note that this does not immediately imply upgrading...
Definition: wallet.cpp:606
ScriptPubKeyMan * GetScriptPubKeyMan() const
Get spkm.
Definition: wallet.cpp:701
bool Upgrade(std::string &error, const int prevVersion)
Upgrade wallet to HD and Sapling if needed.
Definition: wallet.cpp:1824
CAmount GetColdStakingCredit(bool fUseCache=true) const
Definition: wallet.cpp:1694
bool ChangeWalletPassphrase(const SecureString &strOldWalletPassphrase, const SecureString &strNewWalletPassphrase)
Definition: wallet.cpp:457
CBlockIndex * ScanForWalletTransactions(CBlockIndex *pindexStart, CBlockIndex *pindexStop, const WalletRescanReserver &reserver, bool fUpdate=false, bool fromStartup=false)
Scan the block chain (starting in pindexStart) for transactions from or to us.
Definition: wallet.cpp:1896
isminetype IsMine(const CTxIn &txin) const
Definition: wallet.cpp:1448
bool SetMinVersion(enum WalletFeature, WalletBatch *batch_in=nullptr, bool fExplicit=false)
signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVe...
Definition: wallet.cpp:580
bool Unlock(const SecureString &strWalletPassphrase, bool anonimizeOnly=false)
Definition: wallet.cpp:376
CAmount GetDebit(const isminefilter &filter) const
filter decides which addresses will count towards the debit
Definition: wallet.cpp:1580
void BlockUntilSyncedToCurrentChain()
Blocks until the wallet state is up-to-date to /at least/ the current chain at the time this function...
Definition: wallet.cpp:1383
bool AbandonTransaction(const uint256 &hashTx)
Definition: wallet.cpp:1144
bool IsHDEnabled() const
Whether the wallet is hd or not //.
Definition: wallet.cpp:156
void GetAmounts(std::list< COutputEntry > &listReceived, std::list< COutputEntry > &listSent, CAmount &nFee, const isminefilter &filter) const
Definition: wallet.cpp:1754
bool EncryptWallet(const SecureString &strWalletPassphrase)
Definition: wallet.cpp:773
int64_t GetTxTime() const
Definition: wallet.cpp:1541
bool HasSaplingSPKM() const
Definition: wallet.cpp:706
bool IsChange(const CTxOut &txout) const
Definition: wallet.cpp:1515
CAmount GetCredit(const isminefilter &filter, bool recalculate=false) const
Definition: wallet.cpp:1616
std::set< uint256 > GetConflicts() const
Definition: wallet.cpp:2052
CAmount GetStakeDelegationCredit(bool fUseCache=true) const
Definition: wallet.cpp:1699
bool IsSpent(const COutPoint &outpoint) const
Outpoint is spent if any non-conflicted transaction spends it:
Definition: wallet.cpp:720
std::string urlDecode(const std::string &urlEncoded)
Definition: httpserver.cpp:679
std::unique_ptr< CConnman > g_connman
Definition: init.cpp:90
isminetype IsMine(const CKeyStore &keystore, const CTxDestination &dest)
Definition: ismine.cpp:29
isminetype
IsMine() return codes.
Definition: ismine.h:19
@ ISMINE_WATCH_ONLY_ALL
Definition: ismine.h:34
@ ISMINE_SPENDABLE_ALL
Definition: ismine.h:33
@ ISMINE_COLD
Indicates that we have the staking key of a P2CS.
Definition: ismine.h:24
@ ISMINE_SPENDABLE_SHIELDED
Indicates that we have the spending key of a shielded spend/output.
Definition: ismine.h:30
@ ISMINE_SPENDABLE
Definition: ismine.h:22
@ ISMINE_NO
Definition: ismine.h:20
@ ISMINE_WATCH_ONLY
Definition: ismine.h:21
@ ISMINE_SPENDABLE_DELEGATED
Indicates that we have the spending key of a P2CS.
Definition: ismine.h:26
uint8_t isminefilter
used for bitflags of isminetype
Definition: ismine.h:39
@ LOCK
Definition: lockunlock.h:16
CMasternodeSync masternodeSync
const std::string COLD_STAKING
Definition: addressbook.cpp:15
bool IsExchangePurpose(const std::string &purpose)
Definition: addressbook.cpp:32
bool IsColdStakingPurpose(const std::string &purpose)
Definition: addressbook.cpp:22
@ UPGRADE_V6_0
Definition: params.h:41
std::string EncodePaymentAddress(const libzcash::PaymentAddress &zaddr)
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:127
Optional< libzcash::SaplingPaymentAddress > DecodeSaplingPaymentAddress(const std::string &strAddress)
libzcash::PaymentAddress DecodePaymentAddress(const std::string &str)
const CTxDestination * GetTransparentDestination(const CWDestination &dest)
bool IsValidDestination(const CWDestination &address)
std::string EncodeDestination(const CWDestination &address, const CChainParams::Base58Type addrType)
CWDestination DecodeDestination(const std::string &strAddress)
const libzcash::SaplingPaymentAddress * GetShieldedDestination(const CWDestination &dest)
RecursiveMutex cs_main
Global state.
Definition: validation.cpp:80
boost::optional< T > Optional
Substitute for C++17 std::optional.
Definition: optional.h:12
const char * name
Definition: rest.cpp:37
UniValue JSONRPCError(int code, const std::string &message)
Definition: protocol.cpp:53
@ RPC_WALLET_NOT_SPECIFIED
No wallet specified (error when there are multiple wallets loaded)
Definition: protocol.h:80
@ RPC_WALLET_INVALID_LABEL_NAME
Not enough funds in wallet.
Definition: protocol.h:72
@ RPC_WALLET_UNLOCK_NEEDED
Keypool ran out, call keypoolrefill first.
Definition: protocol.h:74
@ RPC_WALLET_ALREADY_UNLOCKED
Failed to encrypt the wallet.
Definition: protocol.h:78
@ RPC_MISC_ERROR
General application defined errors.
Definition: protocol.h:41
@ RPC_WALLET_INSUFFICIENT_FUNDS
Unspecified problem with wallet (key not found etc.)
Definition: protocol.h:71
@ RPC_WALLET_WRONG_ENC_STATE
The wallet passphrase entered was incorrect.
Definition: protocol.h:76
@ RPC_METHOD_NOT_FOUND
Definition: protocol.h:35
@ RPC_WALLET_ENCRYPTION_FAILED
Command given in wrong wallet encryption state (encrypting an encrypted wallet etc....
Definition: protocol.h:77
@ RPC_TYPE_ERROR
Server is in safe mode, and command is not allowed in safe mode.
Definition: protocol.h:43
@ RPC_INVALID_PARAMETER
Ran out of memory during operation.
Definition: protocol.h:46
@ RPC_IN_WARMUP
Transaction already in chain.
Definition: protocol.h:52
@ RPC_WALLET_ERROR
No valid connection manager instance found.
Definition: protocol.h:70
@ RPC_WALLET_NOT_FOUND
Wallet is already unlocked.
Definition: protocol.h:79
@ RPC_INTERNAL_ERROR
Definition: protocol.h:37
@ RPC_WALLET_KEYPOOL_RAN_OUT
Invalid label name.
Definition: protocol.h:73
@ RPC_CLIENT_IN_INITIAL_DOWNLOAD
PIVX is not connected.
Definition: protocol.h:62
@ RPC_DESERIALIZATION_ERROR
Database error.
Definition: protocol.h:48
@ RPC_WALLET_PASSPHRASE_INCORRECT
Enter the wallet passphrase with walletpassphrase first.
Definition: protocol.h:75
@ RPC_INVALID_ADDRESS_OR_KEY
Unexpected type was passed as parameter.
Definition: protocol.h:44
@ RPC_CLIENT_P2P_DISABLED
Invalid IP/Subnet.
Definition: protocol.h:67
@ ownerKey
Definition: rpcevo.cpp:49
UniValue listaddressgroupings(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:1970
UniValue setlabel(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:1019
UniValue rescanblockchain(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:4676
CScript _createmultisig_redeemScript(CWallet *const pwallet, const UniValue &params)
Used by addmultisigaddress / createmultisig:
Definition: misc.cpp:461
UniValue listcoldutxos(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:2912
UniValue delegatestake(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:1335
UniValue rawdelegatestake(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:1391
UniValue listreceivedbyshieldaddress(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:2765
CWallet * GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: rpcwallet.cpp:39
UniValue importpubkey(const JSONRPCRequest &request)
Definition: rpcdump.cpp:273
UniValue liststakingaddresses(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:907
UniValue getautocombinethreshold(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:4603
UniValue lockunspent(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:4040
UniValue listreceivedbyaddress(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:2719
UniValue importprivkey(const JSONRPCRequest &request)
Definition: rpcdump.cpp:78
UniValue addmultisigaddress(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:2516
std::string HelpRequiringPassphrase(CWallet *const pwallet)
Definition: rpcwallet.cpp:54
UniValue listshieldunspent(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:627
UniValue viewshieldtransaction(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:1508
UniValue getrawchangeaddress(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:982
UniValue delegatoradd(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:759
UniValue getaddressinfo(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:147
UniValue delegatorremove(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:799
UniValue getstakingstatus(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:4404
UniValue walletlock(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:3613
UniValue getshieldbalance(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:1451
UniValue bip38decrypt(const JSONRPCRequest &request)
Definition: rpcdump.cpp:1167
UniValue shieldsendmany(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:1856
UniValue settxfee(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:4256
UniValue getstakesplitthreshold(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:4509
UniValue listshieldaddresses(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:935
UniValue sethdseed(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:439
UniValue fundrawtransaction(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:3892
UniValue rawshieldsendmany(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:1918
UniValue listdelegators(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:872
UniValue listreceivedbylabel(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:2871
void RegisterWalletRPCCommands(CRPCTable &tableRPC)
Definition: rpcwallet.cpp:4853
UniValue listlockunspent(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:4184
UniValue exportsaplingkey(const JSONRPCRequest &request)
Definition: rpcdump.cpp:1494
UniValue abandontransaction(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:3363
UniValue dumpwallet(const JSONRPCRequest &request)
Definition: rpcdump.cpp:497
UniValue listtransactions(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:3064
UniValue keypoolrefill(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:3437
UniValue exportsaplingviewingkey(const JSONRPCRequest &request)
Definition: rpcdump.cpp:1451
UniValue getreceivedbyaddress(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:2082
UniValue getwalletinfo(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:4287
bool HaveKey(const CWallet *wallet, const CKey &key)
Checks if a CKey is in the given CWallet compressed or otherwise.
Definition: rpcwallet.cpp:140
UniValue listlabels(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:325
UniValue signmessage(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:2025
UniValue importwallet(const JSONRPCRequest &request)
Definition: rpcdump.cpp:330
UniValue listwallets(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:4373
UniValue setautocombinethreshold(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:4530
UniValue getnewstakingaddress(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:559
UniValue getdelegatedbalance(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:2291
UniValue abortrescan(const JSONRPCRequest &request)
Definition: rpcdump.cpp:152
UniValue sendmany(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:2425
UniValue gettransaction(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:3277
UniValue sendtoaddress(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:1145
UniValue getreceivedbylabel(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:2148
UniValue dumpprivkey(const JSONRPCRequest &request)
Definition: rpcdump.cpp:457
UniValue importaddress(const JSONRPCRequest &request)
Definition: rpcdump.cpp:206
void EnsureWalletIsUnlocked(CWallet *const pwallet, bool fAllowAnonOnly)
Definition: rpcwallet.cpp:71
UniValue getnewshieldaddress(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:584
UniValue importsaplingkey(const JSONRPCRequest &request)
Definition: rpcdump.cpp:1243
UniValue walletpassphrasechange(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:3564
UniValue setstakesplitthreshold(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:4467
UniValue encryptwallet(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:3656
UniValue importsaplingviewingkey(const JSONRPCRequest &request)
Definition: rpcdump.cpp:1345
UniValue getunconfirmedbalance(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:2322
UniValue walletpassphrase(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:3484
bool EnsureWalletIsAvailable(CWallet *const pwallet, bool avoidException)
Definition: rpcwallet.cpp:59
UniValue getbalance(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:2211
UniValue getnewexchangeaddress(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:531
UniValue upgradewallet(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:394
UniValue listsinceblock(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:3184
UniValue listunspent(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:3712
UniValue getaddressesbylabel(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:274
UniValue getnewaddress(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:505
UniValue bip38encrypt(const JSONRPCRequest &request)
Definition: rpcdump.cpp:1116
UniValue importmulti(const JSONRPCRequest &request)
Definition: rpcdump.cpp:960
UniValue getsaplingnotescount(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:4635
UniValue backupwallet(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:3405
std::string LabelFromValue(const UniValue &value)
Definition: rpcwallet.cpp:105
UniValue getcoldstakingbalance(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:2261
CPubKey parseWIFKey(std::string strKey, CWallet *pwallet)
Definition: rpcwallet.cpp:381
#define ZC_MEMO_SIZE
Definition: sapling.h:24
OperationResult CheckTransactionSize(std::vector< SendManyRecipient > &recipients, bool fromTaddr)
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition: secure.h:61
void RPCTypeCheckArgument(const UniValue &value, const UniValueType &typeExpected)
Type-check one argument; throws JSONRPCError if wrong type given.
Definition: server.cpp:82
UniValue ValueFromAmount(const CAmount &amount)
Definition: server.cpp:128
void RPCRunLater(const std::string &name, std::function< void(void)> func, int64_t nSeconds)
Run func nSeconds from now.
Definition: server.cpp:556
std::string HelpExampleCli(std::string methodname, std::string args)
Definition: server.cpp:527
void RPCTypeCheck(const UniValue &params, const std::list< UniValue::VType > &typesExpected, bool fAllowNull)
Type-check arguments; throws JSONRPCError if wrong type given.
Definition: server.cpp:63
CAmount AmountFromValue(const UniValue &value)
Definition: server.cpp:116
uint256 ParseHashO(const UniValue &o, std::string strKey)
Definition: server.cpp:147
uint256 ParseHashV(const UniValue &v, std::string strName)
Utilities: convert hex-encoded Values (throws error if not hex).
Definition: server.cpp:138
std::string HelpExampleRpc(std::string methodname, std::string args)
Definition: server.cpp:532
void RPCTypeCheckObj(const UniValue &o, const std::map< std::string, UniValueType > &typesExpected, bool fAllowNull, bool fStrict)
Check for expected keys/value types in an Object.
Definition: server.cpp:89
CRPCTable tableRPC
Definition: server.cpp:565
CSporkManager sporkManager
Definition: spork.cpp:29
@ SPORK_19_COLDSTAKING_MAINTENANCE
Definition: sporkid.h:26
@ SPORK_20_SAPLING_MAINTENANCE
Definition: sporkid.h:27
bool ExtractDestinations(const CScript &scriptPubKey, txnouttype &typeRet, std::vector< CTxDestination > &addressRet, int &nRequiredRet)
Parse a standard scriptPubKey with one or more destination addresses.
Definition: standard.cpp:195
CScript GetScriptForStakeDelegation(const CKeyID &stakingKey, const CKeyID &spendingKey)
Generate a P2CS script for the given staker and owner keys.
Definition: standard.cpp:291
CScript GetScriptForStakeDelegationLOF(const CKeyID &stakingKey, const CKeyID &spendingKey)
Definition: standard.cpp:301
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a PIVX scriptPubKey for the given CTxDestination.
Definition: standard.cpp:278
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet, bool fColdStake)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:162
boost::variant< CNoDestination, CKeyID, CScriptID, CExchangeKeyID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:72
txnouttype
Definition: standard.h:46
A mutable version of CTransaction.
Definition: transaction.h:409
std::vector< CTxOut > vout
Definition: transaction.h:411
Definition: wallet.h:292
std::set< CTxDestination > * onlyFilteredDest
Definition: wallet.h:813
unsigned int nMaximumCount
Definition: wallet.h:820
CWallet::CommitStatus status
Definition: wallet.h:1106
Parameters that influence chain consensus.
Definition: params.h:171
bool NetworkUpgradeActive(int nHeight, Consensus::UpgradeIndex idx) const
Returns true if the given network upgrade is active as of the given block height.
Definition: params.cpp:12
unsigned char fingerprint[4]
First 32 bits of the Hash160 of the public key at the root of the path.
Definition: keyorigin.h:13
std::string pathToString() const
Definition: keyorigin.h:29
Sapling note, its location in a transaction, and number of confirmations.
Wrapper for UniValue::VType, which includes typeAny: Used to denote don't care type.
Definition: server.h:35
libzcash::SaplingExpandedSpendingKey expsk
Definition: zip32.h:92
std::vector< uint256 > txids
Definition: rpcwallet.cpp:2567
bool fIsWatchonly
Definition: rpcwallet.cpp:2568
CAmount nAmount
Definition: rpcwallet.cpp:2565
#define LOCK2(cs1, cs2)
Definition: sync.h:221
#define AssertLockHeld(cs)
Definition: sync.h:75
ArgsManager gArgs
Definition: system.cpp:89
std::string _(const char *psz)
Translation function: Call Translate signal on UI interface, which returns a Optional result.
Definition: system.h:65
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:50
#define strprintf
Definition: tinyformat.h:1056
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:456
bool IsFinalTx(const CTransactionRef &tx, int nBlockHeight, int64_t nBlockTime)
Check if transaction is final and can be included in a block with the specified height and time.
Definition: tx_verify.cpp:12
const uint256 UINT256_ZERO
constant uint256 instances
Definition: uint256.h:175
uint256 uint256S(const char *str)
Definition: uint256.h:157
const UniValue & find_value(const UniValue &obj, const std::string &name)
Definition: univalue.cpp:234
const UniValue NullUniValue
Definition: univalue.cpp:13
std::string FormatMoney(const CAmount &n, bool fPlus)
Money parsing/formatting utilities.
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
std::string EncodeBase64(Span< const unsigned char > input)
bool IsValidUTF8(const std::string &str)
Checks for valid 4-byte UTF-8 encoding in a string.
#define ARRAYLEN(array)
T FindFirstNonZero(T itbegin, T itend)
int64_t GetTime()
DEPRECATED Use either GetSystemTimeInSeconds (not mockable) or GetTime<T> (mockable)
Definition: utiltime.cpp:27
bool CheckFinalTx(const CTransactionRef &tx, int flags)
Check if transaction will be final in the next block to be created.
Definition: validation.cpp:224
bool IsInitialBlockDownload()
Check whether we are doing an initial block download (synchronizing from disk or network)
Definition: validation.cpp:862
std::unique_ptr< CCoinsViewCache > pcoinsTip
Global variable that points to the active CCoinsView (protected by cs_main)
Definition: validation.cpp:206
BlockMap mapBlockIndex
Definition: validation.cpp:82
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:84
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Definition: validation.h:345
std::vector< CWalletRef > vpwallets
Definition: wallet.cpp:33
CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE)
Settings.
@ FEATURE_SAPLING
Definition: wallet.h:118
@ FEATURE_PRE_SPLIT_KEYPOOL
Definition: wallet.h:116
@ FEATURE_LATEST
Definition: wallet.h:120