Bitcoin Core  0.20.99
P2P Digital Currency
rpcwallet.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2020 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <amount.h>
7 #include <core_io.h>
8 #include <interfaces/chain.h>
9 #include <key_io.h>
10 #include <node/context.h>
11 #include <outputtype.h>
12 #include <policy/feerate.h>
13 #include <policy/fees.h>
14 #include <policy/rbf.h>
16 #include <rpc/server.h>
17 #include <rpc/util.h>
18 #include <script/descriptor.h>
19 #include <script/sign.h>
20 #include <util/bip32.h>
21 #include <util/fees.h>
22 #include <util/message.h> // For MessageSign()
23 #include <util/moneystr.h>
24 #include <util/string.h>
25 #include <util/system.h>
26 #include <util/translation.h>
27 #include <util/url.h>
28 #include <util/vector.h>
29 #include <wallet/coincontrol.h>
30 #include <wallet/feebumper.h>
31 #include <wallet/rpcwallet.h>
32 #include <wallet/wallet.h>
33 #include <wallet/walletdb.h>
34 #include <wallet/walletutil.h>
35 
36 #include <stdint.h>
37 
38 #include <univalue.h>
39 
40 
42 
43 static const std::string WALLET_ENDPOINT_BASE = "/wallet/";
44 static const std::string HELP_REQUIRING_PASSPHRASE{"\nRequires wallet passphrase to be set with walletpassphrase call if wallet is encrypted.\n"};
45 
46 static inline bool GetAvoidReuseFlag(const CWallet* const pwallet, const UniValue& param) {
47  bool can_avoid_reuse = pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE);
48  bool avoid_reuse = param.isNull() ? can_avoid_reuse : param.get_bool();
49 
50  if (avoid_reuse && !can_avoid_reuse) {
51  throw JSONRPCError(RPC_WALLET_ERROR, "wallet does not have the \"avoid reuse\" feature enabled");
52  }
53 
54  return avoid_reuse;
55 }
56 
57 
62 static bool ParseIncludeWatchonly(const UniValue& include_watchonly, const CWallet& pwallet)
63 {
64  if (include_watchonly.isNull()) {
65  // if include_watchonly isn't explicitly set, then check if we have a watchonly wallet
67  }
68 
69  // otherwise return whatever include_watchonly was set to
70  return include_watchonly.get_bool();
71 }
72 
73 
75 bool HaveKey(const SigningProvider& wallet, const CKey& key)
76 {
77  CKey key2;
78  key2.Set(key.begin(), key.end(), !key.IsCompressed());
79  return wallet.HaveKey(key.GetPubKey().GetID()) || wallet.HaveKey(key2.GetPubKey().GetID());
80 }
81 
82 bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest& request, std::string& wallet_name)
83 {
84  if (URL_DECODE && request.URI.substr(0, WALLET_ENDPOINT_BASE.size()) == WALLET_ENDPOINT_BASE) {
85  // wallet endpoint was used
86  wallet_name = URL_DECODE(request.URI.substr(WALLET_ENDPOINT_BASE.size()));
87  return true;
88  }
89  return false;
90 }
91 
92 std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request)
93 {
94  std::string wallet_name;
95  if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
96  std::shared_ptr<CWallet> pwallet = GetWallet(wallet_name);
97  if (!pwallet) throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
98  return pwallet;
99  }
100 
101  std::vector<std::shared_ptr<CWallet>> wallets = GetWallets();
102  return wallets.size() == 1 || (request.fHelp && wallets.size() > 0) ? wallets[0] : nullptr;
103 }
104 
105 bool EnsureWalletIsAvailable(const CWallet* pwallet, bool avoidException)
106 {
107  if (pwallet) return true;
108  if (avoidException) return false;
109  if (!HasWallets()) {
110  throw JSONRPCError(
111  RPC_METHOD_NOT_FOUND, "Method not found (wallet method is disabled because no wallet is loaded)");
112  }
114  "Wallet file not specified (must request wallet RPC through /wallet/<filename> uri-path).");
115 }
116 
117 void EnsureWalletIsUnlocked(const CWallet* pwallet)
118 {
119  if (pwallet->IsLocked()) {
120  throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
121  }
122 }
123 
124 // also_create should only be set to true only when the RPC is expected to add things to a blank wallet and make it no longer blank
126 {
128  if (!spk_man && also_create) {
129  spk_man = wallet.GetOrCreateLegacyScriptPubKeyMan();
130  }
131  if (!spk_man) {
132  throw JSONRPCError(RPC_WALLET_ERROR, "This type of wallet does not support this command");
133  }
134  return *spk_man;
135 }
136 
137 static void WalletTxToJSON(interfaces::Chain& chain, const CWalletTx& wtx, UniValue& entry)
138 {
139  int confirms = wtx.GetDepthInMainChain();
140  entry.pushKV("confirmations", confirms);
141  if (wtx.IsCoinBase())
142  entry.pushKV("generated", true);
143  if (confirms > 0)
144  {
145  entry.pushKV("blockhash", wtx.m_confirm.hashBlock.GetHex());
146  entry.pushKV("blockheight", wtx.m_confirm.block_height);
147  entry.pushKV("blockindex", wtx.m_confirm.nIndex);
148  int64_t block_time;
149  CHECK_NONFATAL(chain.findBlock(wtx.m_confirm.hashBlock, FoundBlock().time(block_time)));
150  entry.pushKV("blocktime", block_time);
151  } else {
152  entry.pushKV("trusted", wtx.IsTrusted());
153  }
154  uint256 hash = wtx.GetHash();
155  entry.pushKV("txid", hash.GetHex());
156  UniValue conflicts(UniValue::VARR);
157  for (const uint256& conflict : wtx.GetConflicts())
158  conflicts.push_back(conflict.GetHex());
159  entry.pushKV("walletconflicts", conflicts);
160  entry.pushKV("time", wtx.GetTxTime());
161  entry.pushKV("timereceived", (int64_t)wtx.nTimeReceived);
162 
163  // Add opt-in RBF status
164  std::string rbfStatus = "no";
165  if (confirms <= 0) {
166  RBFTransactionState rbfState = chain.isRBFOptIn(*wtx.tx);
167  if (rbfState == RBFTransactionState::UNKNOWN)
168  rbfStatus = "unknown";
169  else if (rbfState == RBFTransactionState::REPLACEABLE_BIP125)
170  rbfStatus = "yes";
171  }
172  entry.pushKV("bip125-replaceable", rbfStatus);
173 
174  for (const std::pair<const std::string, std::string>& item : wtx.mapValue)
175  entry.pushKV(item.first, item.second);
176 }
177 
178 static std::string LabelFromValue(const UniValue& value)
179 {
180  std::string label = value.get_str();
181  if (label == "*")
182  throw JSONRPCError(RPC_WALLET_INVALID_LABEL_NAME, "Invalid label name");
183  return label;
184 }
185 
186 static UniValue getnewaddress(const JSONRPCRequest& request)
187 {
188  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
189  CWallet* const pwallet = wallet.get();
190 
191  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
192  return NullUniValue;
193  }
194 
195  RPCHelpMan{"getnewaddress",
196  "\nReturns a new Bitcoin address for receiving payments.\n"
197  "If 'label' is specified, it is added to the address book \n"
198  "so payments received with the address will be associated with 'label'.\n",
199  {
200  {"label", RPCArg::Type::STR, /* default */ "\"\"", "The label name for the address to be linked to. 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."},
201  {"address_type", RPCArg::Type::STR, /* default */ "set by -addresstype", "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
202  },
203  RPCResult{
204  RPCResult::Type::STR, "address", "The new bitcoin address"
205  },
206  RPCExamples{
207  HelpExampleCli("getnewaddress", "")
208  + HelpExampleRpc("getnewaddress", "")
209  },
210  }.Check(request);
211 
212  LOCK(pwallet->cs_wallet);
213 
214  if (!pwallet->CanGetAddresses()) {
215  throw JSONRPCError(RPC_WALLET_ERROR, "Error: This wallet has no available keys");
216  }
217 
218  // Parse the label first so we don't generate a key if there's an error
219  std::string label;
220  if (!request.params[0].isNull())
221  label = LabelFromValue(request.params[0]);
222 
223  OutputType output_type = pwallet->m_default_address_type;
224  if (!request.params[1].isNull()) {
225  if (!ParseOutputType(request.params[1].get_str(), output_type)) {
226  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[1].get_str()));
227  }
228  }
229 
230  CTxDestination dest;
231  std::string error;
232  if (!pwallet->GetNewDestination(output_type, label, dest, error)) {
234  }
235 
236  return EncodeDestination(dest);
237 }
238 
240 {
241  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
242  CWallet* const pwallet = wallet.get();
243 
244  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
245  return NullUniValue;
246  }
247 
248  RPCHelpMan{"getrawchangeaddress",
249  "\nReturns a new Bitcoin address, for receiving change.\n"
250  "This is for use with raw transactions, NOT normal use.\n",
251  {
252  {"address_type", RPCArg::Type::STR, /* default */ "set by -changetype", "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
253  },
254  RPCResult{
255  RPCResult::Type::STR, "address", "The address"
256  },
257  RPCExamples{
258  HelpExampleCli("getrawchangeaddress", "")
259  + HelpExampleRpc("getrawchangeaddress", "")
260  },
261  }.Check(request);
262 
263  LOCK(pwallet->cs_wallet);
264 
265  if (!pwallet->CanGetAddresses(true)) {
266  throw JSONRPCError(RPC_WALLET_ERROR, "Error: This wallet has no available keys");
267  }
268 
270  if (!request.params[0].isNull()) {
271  if (!ParseOutputType(request.params[0].get_str(), output_type)) {
272  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[0].get_str()));
273  }
274  }
275 
276  CTxDestination dest;
277  std::string error;
278  if (!pwallet->GetNewChangeDestination(output_type, dest, error)) {
280  }
281  return EncodeDestination(dest);
282 }
283 
284 
285 static UniValue setlabel(const JSONRPCRequest& request)
286 {
287  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
288  CWallet* const pwallet = wallet.get();
289 
290  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
291  return NullUniValue;
292  }
293 
294  RPCHelpMan{"setlabel",
295  "\nSets the label associated with the given address.\n",
296  {
297  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to be associated with a label."},
298  {"label", RPCArg::Type::STR, RPCArg::Optional::NO, "The label to assign to the address."},
299  },
301  RPCExamples{
302  HelpExampleCli("setlabel", "\"" + EXAMPLE_ADDRESS[0] + "\" \"tabby\"")
303  + HelpExampleRpc("setlabel", "\"" + EXAMPLE_ADDRESS[0] + "\", \"tabby\"")
304  },
305  }.Check(request);
306 
307  LOCK(pwallet->cs_wallet);
308 
309  CTxDestination dest = DecodeDestination(request.params[0].get_str());
310  if (!IsValidDestination(dest)) {
311  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
312  }
313 
314  std::string label = LabelFromValue(request.params[1]);
315 
316  if (pwallet->IsMine(dest)) {
317  pwallet->SetAddressBook(dest, label, "receive");
318  } else {
319  pwallet->SetAddressBook(dest, label, "send");
320  }
321 
322  return NullUniValue;
323 }
324 
325 
326 static CTransactionRef SendMoney(CWallet* const pwallet, const CTxDestination& address, CAmount nValue, bool fSubtractFeeFromAmount, const CCoinControl& coin_control, mapValue_t mapValue)
327 {
328  CAmount curBalance = pwallet->GetBalance(0, coin_control.m_avoid_address_reuse).m_mine_trusted;
329 
330  // Check amount
331  if (nValue <= 0)
332  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid amount");
333 
334  if (nValue > curBalance)
335  throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds");
336 
337  // Parse Bitcoin address
338  CScript scriptPubKey = GetScriptForDestination(address);
339 
340  // Create and send the transaction
341  CAmount nFeeRequired = 0;
343  std::vector<CRecipient> vecSend;
344  int nChangePosRet = -1;
345  CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
346  vecSend.push_back(recipient);
347  CTransactionRef tx;
348  if (!pwallet->CreateTransaction(vecSend, tx, nFeeRequired, nChangePosRet, error, coin_control)) {
349  if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance)
350  error = strprintf(Untranslated("Error: This transaction requires a transaction fee of at least %s"), FormatMoney(nFeeRequired));
351  throw JSONRPCError(RPC_WALLET_ERROR, error.original);
352  }
353  pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */);
354  return tx;
355 }
356 
357 static UniValue sendtoaddress(const JSONRPCRequest& request)
358 {
359  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
360  CWallet* const pwallet = wallet.get();
361 
362  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
363  return NullUniValue;
364  }
365 
366  RPCHelpMan{"sendtoaddress",
367  "\nSend an amount to a given address." +
369  {
370  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to send to."},
371  {"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The amount in " + CURRENCY_UNIT + " to send. eg 0.1"},
372  {"comment", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "A comment used to store what the transaction is for.\n"
373  " This is not part of the transaction, just kept in your wallet."},
374  {"comment_to", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "A comment to store the name of the person or organization\n"
375  " to which you're sending the transaction. This is not part of the \n"
376  " transaction, just kept in your wallet."},
377  {"subtractfeefromamount", RPCArg::Type::BOOL, /* default */ "false", "The fee will be deducted from the amount being sent.\n"
378  " The recipient will receive less bitcoins than you enter in the amount field."},
379  {"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Allow this transaction to be replaced by a transaction with higher fees via BIP 125"},
380  {"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks)"},
381  {"estimate_mode", RPCArg::Type::STR, /* default */ "UNSET", "The fee estimate mode, must be one of:\n"
382  " \"UNSET\"\n"
383  " \"ECONOMICAL\"\n"
384  " \"CONSERVATIVE\""},
385  {"avoid_reuse", RPCArg::Type::BOOL, /* default */ "true", "(only available if avoid_reuse wallet flag is set) Avoid spending from dirty addresses; addresses are considered\n"
386  " dirty if they have previously been used in a transaction."},
387  },
388  RPCResult{
389  RPCResult::Type::STR_HEX, "txid", "The transaction id."
390  },
391  RPCExamples{
392  HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1")
393  + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"donation\" \"seans outpost\"")
394  + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"\" \"\" true")
395  + HelpExampleRpc("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\", 0.1, \"donation\", \"seans outpost\"")
396  },
397  }.Check(request);
398 
399  // Make sure the results are valid at least up to the most recent block
400  // the user could have gotten from another RPC command prior to now
402 
403  LOCK(pwallet->cs_wallet);
404 
405  CTxDestination dest = DecodeDestination(request.params[0].get_str());
406  if (!IsValidDestination(dest)) {
407  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
408  }
409 
410  // Amount
411  CAmount nAmount = AmountFromValue(request.params[1]);
412  if (nAmount <= 0)
413  throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
414 
415  // Wallet comments
416  mapValue_t mapValue;
417  if (!request.params[2].isNull() && !request.params[2].get_str().empty())
418  mapValue["comment"] = request.params[2].get_str();
419  if (!request.params[3].isNull() && !request.params[3].get_str().empty())
420  mapValue["to"] = request.params[3].get_str();
421 
422  bool fSubtractFeeFromAmount = false;
423  if (!request.params[4].isNull()) {
424  fSubtractFeeFromAmount = request.params[4].get_bool();
425  }
426 
427  CCoinControl coin_control;
428  if (!request.params[5].isNull()) {
429  coin_control.m_signal_bip125_rbf = request.params[5].get_bool();
430  }
431 
432  if (!request.params[6].isNull()) {
433  coin_control.m_confirm_target = ParseConfirmTarget(request.params[6], pwallet->chain().estimateMaxBlocks());
434  }
435 
436  if (!request.params[7].isNull()) {
437  if (!FeeModeFromString(request.params[7].get_str(), coin_control.m_fee_mode)) {
438  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter");
439  }
440  }
441 
442  coin_control.m_avoid_address_reuse = GetAvoidReuseFlag(pwallet, request.params[8]);
443  // We also enable partial spend avoidance if reuse avoidance is set.
444  coin_control.m_avoid_partial_spends |= coin_control.m_avoid_address_reuse;
445 
446  EnsureWalletIsUnlocked(pwallet);
447 
448  CTransactionRef tx = SendMoney(pwallet, dest, nAmount, fSubtractFeeFromAmount, coin_control, std::move(mapValue));
449  return tx->GetHash().GetHex();
450 }
451 
453 {
454  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
455  const CWallet* const pwallet = wallet.get();
456 
457  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
458  return NullUniValue;
459  }
460 
461  RPCHelpMan{"listaddressgroupings",
462  "\nLists groups of addresses which have had their common ownership\n"
463  "made public by common use as inputs or as the resulting change\n"
464  "in past transactions\n",
465  {},
466  RPCResult{
467  RPCResult::Type::ARR, "", "",
468  {
469  {RPCResult::Type::ARR, "", "",
470  {
471  {RPCResult::Type::ARR, "", "",
472  {
473  {RPCResult::Type::STR, "address", "The bitcoin address"},
474  {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT},
475  {RPCResult::Type::STR, "label", /* optional */ true, "The label"},
476  }},
477  }},
478  }
479  },
480  RPCExamples{
481  HelpExampleCli("listaddressgroupings", "")
482  + HelpExampleRpc("listaddressgroupings", "")
483  },
484  }.Check(request);
485 
486  // Make sure the results are valid at least up to the most recent block
487  // the user could have gotten from another RPC command prior to now
489 
490  LOCK(pwallet->cs_wallet);
491 
492  UniValue jsonGroupings(UniValue::VARR);
493  std::map<CTxDestination, CAmount> balances = pwallet->GetAddressBalances();
494  for (const std::set<CTxDestination>& grouping : pwallet->GetAddressGroupings()) {
495  UniValue jsonGrouping(UniValue::VARR);
496  for (const CTxDestination& address : grouping)
497  {
498  UniValue addressInfo(UniValue::VARR);
499  addressInfo.push_back(EncodeDestination(address));
500  addressInfo.push_back(ValueFromAmount(balances[address]));
501  {
502  const auto* address_book_entry = pwallet->FindAddressBookEntry(address);
503  if (address_book_entry) {
504  addressInfo.push_back(address_book_entry->GetLabel());
505  }
506  }
507  jsonGrouping.push_back(addressInfo);
508  }
509  jsonGroupings.push_back(jsonGrouping);
510  }
511  return jsonGroupings;
512 }
513 
514 static UniValue signmessage(const JSONRPCRequest& request)
515 {
516  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
517  const CWallet* const pwallet = wallet.get();
518 
519  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
520  return NullUniValue;
521  }
522 
523  RPCHelpMan{"signmessage",
524  "\nSign a message with the private key of an address" +
526  {
527  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to use for the private key."},
528  {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message to create a signature of."},
529  },
530  RPCResult{
531  RPCResult::Type::STR, "signature", "The signature of the message encoded in base 64"
532  },
533  RPCExamples{
534  "\nUnlock the wallet for 30 seconds\n"
535  + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
536  "\nCreate the signature\n"
537  + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") +
538  "\nVerify the signature\n"
539  + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
540  "\nAs a JSON-RPC call\n"
541  + HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"my message\"")
542  },
543  }.Check(request);
544 
545  LOCK(pwallet->cs_wallet);
546 
547  EnsureWalletIsUnlocked(pwallet);
548 
549  std::string strAddress = request.params[0].get_str();
550  std::string strMessage = request.params[1].get_str();
551 
552  CTxDestination dest = DecodeDestination(strAddress);
553  if (!IsValidDestination(dest)) {
554  throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
555  }
556 
557  const PKHash *pkhash = boost::get<PKHash>(&dest);
558  if (!pkhash) {
559  throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
560  }
561 
562  std::string signature;
563  SigningResult err = pwallet->SignMessage(strMessage, *pkhash, signature);
564  if (err == SigningResult::SIGNING_FAILED) {
566  } else if (err != SigningResult::OK){
568  }
569 
570  return signature;
571 }
572 
573 static CAmount GetReceived(const CWallet& wallet, const UniValue& params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
574 {
575  std::set<CTxDestination> address_set;
576 
577  if (by_label) {
578  // Get the set of addresses assigned to label
579  std::string label = LabelFromValue(params[0]);
580  address_set = wallet.GetLabelAddresses(label);
581  } else {
582  // Get the address
583  CTxDestination dest = DecodeDestination(params[0].get_str());
584  if (!IsValidDestination(dest)) {
585  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
586  }
587  CScript script_pub_key = GetScriptForDestination(dest);
588  if (!wallet.IsMine(script_pub_key)) {
589  throw JSONRPCError(RPC_WALLET_ERROR, "Address not found in wallet");
590  }
591  address_set.insert(dest);
592  }
593 
594  // Minimum confirmations
595  int min_depth = 1;
596  if (!params[1].isNull())
597  min_depth = params[1].get_int();
598 
599  // Tally
600  CAmount amount = 0;
601  for (const std::pair<const uint256, CWalletTx>& wtx_pair : wallet.mapWallet) {
602  const CWalletTx& wtx = wtx_pair.second;
603  if (wtx.IsCoinBase() || !wallet.chain().checkFinalTx(*wtx.tx) || wtx.GetDepthInMainChain() < min_depth) {
604  continue;
605  }
606 
607  for (const CTxOut& txout : wtx.tx->vout) {
608  CTxDestination address;
609  if (ExtractDestination(txout.scriptPubKey, address) && wallet.IsMine(address) && address_set.count(address)) {
610  amount += txout.nValue;
611  }
612  }
613  }
614 
615  return amount;
616 }
617 
618 
620 {
621  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
622  const CWallet* const pwallet = wallet.get();
623 
624  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
625  return NullUniValue;
626  }
627 
628  RPCHelpMan{"getreceivedbyaddress",
629  "\nReturns the total amount received by the given address in transactions with at least minconf confirmations.\n",
630  {
631  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address for transactions."},
632  {"minconf", RPCArg::Type::NUM, /* default */ "1", "Only include transactions confirmed at least this many times."},
633  },
634  RPCResult{
635  RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " received at this address."
636  },
637  RPCExamples{
638  "\nThe amount from transactions with at least 1 confirmation\n"
639  + HelpExampleCli("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\"") +
640  "\nThe amount including unconfirmed transactions, zero confirmations\n"
641  + HelpExampleCli("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0") +
642  "\nThe amount with at least 6 confirmations\n"
643  + HelpExampleCli("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 6") +
644  "\nAs a JSON-RPC call\n"
645  + HelpExampleRpc("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\", 6")
646  },
647  }.Check(request);
648 
649  // Make sure the results are valid at least up to the most recent block
650  // the user could have gotten from another RPC command prior to now
652 
653  LOCK(pwallet->cs_wallet);
654 
655  return ValueFromAmount(GetReceived(*pwallet, request.params, /* by_label */ false));
656 }
657 
658 
660 {
661  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
662  const CWallet* const pwallet = wallet.get();
663 
664  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
665  return NullUniValue;
666  }
667 
668  RPCHelpMan{"getreceivedbylabel",
669  "\nReturns the total amount received by addresses with <label> in transactions with at least [minconf] confirmations.\n",
670  {
671  {"label", RPCArg::Type::STR, RPCArg::Optional::NO, "The selected label, may be the default label using \"\"."},
672  {"minconf", RPCArg::Type::NUM, /* default */ "1", "Only include transactions confirmed at least this many times."},
673  },
674  RPCResult{
675  RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " received for this label."
676  },
677  RPCExamples{
678  "\nAmount received by the default label with at least 1 confirmation\n"
679  + HelpExampleCli("getreceivedbylabel", "\"\"") +
680  "\nAmount received at the tabby label including unconfirmed amounts with zero confirmations\n"
681  + HelpExampleCli("getreceivedbylabel", "\"tabby\" 0") +
682  "\nThe amount with at least 6 confirmations\n"
683  + HelpExampleCli("getreceivedbylabel", "\"tabby\" 6") +
684  "\nAs a JSON-RPC call\n"
685  + HelpExampleRpc("getreceivedbylabel", "\"tabby\", 6")
686  },
687  }.Check(request);
688 
689  // Make sure the results are valid at least up to the most recent block
690  // the user could have gotten from another RPC command prior to now
692 
693  LOCK(pwallet->cs_wallet);
694 
695  return ValueFromAmount(GetReceived(*pwallet, request.params, /* by_label */ true));
696 }
697 
698 
699 static UniValue getbalance(const JSONRPCRequest& request)
700 {
701  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
702  const CWallet* const pwallet = wallet.get();
703 
704  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
705  return NullUniValue;
706  }
707 
708  RPCHelpMan{"getbalance",
709  "\nReturns the total available balance.\n"
710  "The available balance is what the wallet considers currently spendable, and is\n"
711  "thus affected by options which limit spendability such as -spendzeroconfchange.\n",
712  {
713  {"dummy", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "Remains for backward compatibility. Must be excluded or set to \"*\"."},
714  {"minconf", RPCArg::Type::NUM, /* default */ "0", "Only include transactions confirmed at least this many times."},
715  {"include_watchonly", RPCArg::Type::BOOL, /* default */ "true for watch-only wallets, otherwise false", "Also include balance in watch-only addresses (see 'importaddress')"},
716  {"avoid_reuse", RPCArg::Type::BOOL, /* default */ "true", "(only available if avoid_reuse wallet flag is set) Do not include balance in dirty outputs; addresses are considered dirty if they have previously been used in a transaction."},
717  },
718  RPCResult{
719  RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " received for this wallet."
720  },
721  RPCExamples{
722  "\nThe total amount in the wallet with 0 or more confirmations\n"
723  + HelpExampleCli("getbalance", "") +
724  "\nThe total amount in the wallet with at least 6 confirmations\n"
725  + HelpExampleCli("getbalance", "\"*\" 6") +
726  "\nAs a JSON-RPC call\n"
727  + HelpExampleRpc("getbalance", "\"*\", 6")
728  },
729  }.Check(request);
730 
731  // Make sure the results are valid at least up to the most recent block
732  // the user could have gotten from another RPC command prior to now
734 
735  LOCK(pwallet->cs_wallet);
736 
737  const UniValue& dummy_value = request.params[0];
738  if (!dummy_value.isNull() && dummy_value.get_str() != "*") {
739  throw JSONRPCError(RPC_METHOD_DEPRECATED, "dummy first argument must be excluded or set to \"*\".");
740  }
741 
742  int min_depth = 0;
743  if (!request.params[1].isNull()) {
744  min_depth = request.params[1].get_int();
745  }
746 
747  bool include_watchonly = ParseIncludeWatchonly(request.params[2], *pwallet);
748 
749  bool avoid_reuse = GetAvoidReuseFlag(pwallet, request.params[3]);
750 
751  const auto bal = pwallet->GetBalance(min_depth, avoid_reuse);
752 
753  return ValueFromAmount(bal.m_mine_trusted + (include_watchonly ? bal.m_watchonly_trusted : 0));
754 }
755 
757 {
758  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
759  const CWallet* const pwallet = wallet.get();
760 
761  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
762  return NullUniValue;
763  }
764 
765  RPCHelpMan{"getunconfirmedbalance",
766  "DEPRECATED\nIdentical to getbalances().mine.untrusted_pending\n",
767  {},
768  RPCResult{RPCResult::Type::NUM, "", "The balance"},
769  RPCExamples{""},
770  }.Check(request);
771 
772  // Make sure the results are valid at least up to the most recent block
773  // the user could have gotten from another RPC command prior to now
775 
776  LOCK(pwallet->cs_wallet);
777 
779 }
780 
781 
782 static UniValue sendmany(const JSONRPCRequest& request)
783 {
784  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
785  CWallet* const pwallet = wallet.get();
786 
787  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
788  return NullUniValue;
789  }
790 
791  RPCHelpMan{"sendmany",
792  "\nSend multiple times. Amounts are double-precision floating point numbers." +
794  {
795  {"dummy", RPCArg::Type::STR, RPCArg::Optional::NO, "Must be set to \"\" for backwards compatibility.", "\"\""},
796  {"amounts", RPCArg::Type::OBJ, RPCArg::Optional::NO, "The addresses and amounts",
797  {
798  {"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The bitcoin address is the key, the numeric amount (can be string) in " + CURRENCY_UNIT + " is the value"},
799  },
800  },
801  {"minconf", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "Ignored dummy value"},
802  {"comment", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "A comment"},
803  {"subtractfeefrom", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "The addresses.\n"
804  " The fee will be equally deducted from the amount of each selected address.\n"
805  " Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
806  " If no addresses are specified here, the sender pays the fee.",
807  {
808  {"address", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Subtract fee from this address"},
809  },
810  },
811  {"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Allow this transaction to be replaced by a transaction with higher fees via BIP 125"},
812  {"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks)"},
813  {"estimate_mode", RPCArg::Type::STR, /* default */ "UNSET", "The fee estimate mode, must be one of:\n"
814  " \"UNSET\"\n"
815  " \"ECONOMICAL\"\n"
816  " \"CONSERVATIVE\""},
817  },
818  RPCResult{
819  RPCResult::Type::STR_HEX, "txid", "The transaction id for the send. Only 1 transaction is created regardless of\n"
820  "the number of addresses."
821  },
822  RPCExamples{
823  "\nSend two amounts to two different addresses:\n"
824  + HelpExampleCli("sendmany", "\"\" \"{\\\"" + EXAMPLE_ADDRESS[0] + "\\\":0.01,\\\"" + EXAMPLE_ADDRESS[1] + "\\\":0.02}\"") +
825  "\nSend two amounts to two different addresses setting the confirmation and comment:\n"
826  + HelpExampleCli("sendmany", "\"\" \"{\\\"" + EXAMPLE_ADDRESS[0] + "\\\":0.01,\\\"" + EXAMPLE_ADDRESS[1] + "\\\":0.02}\" 6 \"testing\"") +
827  "\nSend two amounts to two different addresses, subtract fee from amount:\n"
828  + HelpExampleCli("sendmany", "\"\" \"{\\\"" + EXAMPLE_ADDRESS[0] + "\\\":0.01,\\\"" + EXAMPLE_ADDRESS[1] + "\\\":0.02}\" 1 \"\" \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"") +
829  "\nAs a JSON-RPC call\n"
830  + HelpExampleRpc("sendmany", "\"\", {\"" + EXAMPLE_ADDRESS[0] + "\":0.01,\"" + EXAMPLE_ADDRESS[1] + "\":0.02}, 6, \"testing\"")
831  },
832  }.Check(request);
833 
834  // Make sure the results are valid at least up to the most recent block
835  // the user could have gotten from another RPC command prior to now
837 
838  LOCK(pwallet->cs_wallet);
839 
840  if (!request.params[0].isNull() && !request.params[0].get_str().empty()) {
841  throw JSONRPCError(RPC_INVALID_PARAMETER, "Dummy value must be set to \"\"");
842  }
843  UniValue sendTo = request.params[1].get_obj();
844 
845  mapValue_t mapValue;
846  if (!request.params[3].isNull() && !request.params[3].get_str().empty())
847  mapValue["comment"] = request.params[3].get_str();
848 
849  UniValue subtractFeeFromAmount(UniValue::VARR);
850  if (!request.params[4].isNull())
851  subtractFeeFromAmount = request.params[4].get_array();
852 
853  CCoinControl coin_control;
854  if (!request.params[5].isNull()) {
855  coin_control.m_signal_bip125_rbf = request.params[5].get_bool();
856  }
857 
858  if (!request.params[6].isNull()) {
859  coin_control.m_confirm_target = ParseConfirmTarget(request.params[6], pwallet->chain().estimateMaxBlocks());
860  }
861 
862  if (!request.params[7].isNull()) {
863  if (!FeeModeFromString(request.params[7].get_str(), coin_control.m_fee_mode)) {
864  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter");
865  }
866  }
867 
868  std::set<CTxDestination> destinations;
869  std::vector<CRecipient> vecSend;
870 
871  std::vector<std::string> keys = sendTo.getKeys();
872  for (const std::string& name_ : keys) {
873  CTxDestination dest = DecodeDestination(name_);
874  if (!IsValidDestination(dest)) {
875  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + name_);
876  }
877 
878  if (destinations.count(dest)) {
879  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
880  }
881  destinations.insert(dest);
882 
883  CScript scriptPubKey = GetScriptForDestination(dest);
884  CAmount nAmount = AmountFromValue(sendTo[name_]);
885  if (nAmount <= 0)
886  throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
887 
888  bool fSubtractFeeFromAmount = false;
889  for (unsigned int idx = 0; idx < subtractFeeFromAmount.size(); idx++) {
890  const UniValue& addr = subtractFeeFromAmount[idx];
891  if (addr.get_str() == name_)
892  fSubtractFeeFromAmount = true;
893  }
894 
895  CRecipient recipient = {scriptPubKey, nAmount, fSubtractFeeFromAmount};
896  vecSend.push_back(recipient);
897  }
898 
899  EnsureWalletIsUnlocked(pwallet);
900 
901  // Shuffle recipient list
902  std::shuffle(vecSend.begin(), vecSend.end(), FastRandomContext());
903 
904  // Send
905  CAmount nFeeRequired = 0;
906  int nChangePosRet = -1;
908  CTransactionRef tx;
909  bool fCreated = pwallet->CreateTransaction(vecSend, tx, nFeeRequired, nChangePosRet, error, coin_control);
910  if (!fCreated)
912  pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */);
913  return tx->GetHash().GetHex();
914 }
915 
917 {
918  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
919  CWallet* const pwallet = wallet.get();
920 
921  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
922  return NullUniValue;
923  }
924 
925  RPCHelpMan{"addmultisigaddress",
926  "\nAdd an nrequired-to-sign multisignature address to the wallet. Requires a new wallet backup.\n"
927  "Each key is a Bitcoin address or hex-encoded public key.\n"
928  "This functionality is only intended for use with non-watchonly addresses.\n"
929  "See `importaddress` for watchonly p2sh address support.\n"
930  "If 'label' is specified, assign address to that label.\n",
931  {
932  {"nrequired", RPCArg::Type::NUM, RPCArg::Optional::NO, "The number of required signatures out of the n keys or addresses."},
933  {"keys", RPCArg::Type::ARR, RPCArg::Optional::NO, "The bitcoin addresses or hex-encoded public keys",
934  {
935  {"key", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "bitcoin address or hex-encoded public key"},
936  },
937  },
938  {"label", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "A label to assign the addresses to."},
939  {"address_type", RPCArg::Type::STR, /* default */ "set by -addresstype", "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
940  },
941  RPCResult{
942  RPCResult::Type::OBJ, "", "",
943  {
944  {RPCResult::Type::STR, "address", "The value of the new multisig address"},
945  {RPCResult::Type::STR_HEX, "redeemScript", "The string value of the hex-encoded redemption script"},
946  {RPCResult::Type::STR, "descriptor", "The descriptor for this multisig"},
947  }
948  },
949  RPCExamples{
950  "\nAdd a multisig address from 2 addresses\n"
951  + HelpExampleCli("addmultisigaddress", "2 \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"") +
952  "\nAs a JSON-RPC call\n"
953  + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"")
954  },
955  }.Check(request);
956 
958 
959  LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore);
960 
961  std::string label;
962  if (!request.params[2].isNull())
963  label = LabelFromValue(request.params[2]);
964 
965  int required = request.params[0].get_int();
966 
967  // Get the public keys
968  const UniValue& keys_or_addrs = request.params[1].get_array();
969  std::vector<CPubKey> pubkeys;
970  for (unsigned int i = 0; i < keys_or_addrs.size(); ++i) {
971  if (IsHex(keys_or_addrs[i].get_str()) && (keys_or_addrs[i].get_str().length() == 66 || keys_or_addrs[i].get_str().length() == 130)) {
972  pubkeys.push_back(HexToPubKey(keys_or_addrs[i].get_str()));
973  } else {
974  pubkeys.push_back(AddrToPubKey(spk_man, keys_or_addrs[i].get_str()));
975  }
976  }
977 
978  OutputType output_type = pwallet->m_default_address_type;
979  if (!request.params[3].isNull()) {
980  if (!ParseOutputType(request.params[3].get_str(), output_type)) {
981  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[3].get_str()));
982  }
983  }
984 
985  // Construct using pay-to-script-hash:
986  CScript inner;
987  CTxDestination dest = AddAndGetMultisigDestination(required, pubkeys, output_type, spk_man, inner);
988  pwallet->SetAddressBook(dest, label, "send");
989 
990  // Make the descriptor
991  std::unique_ptr<Descriptor> descriptor = InferDescriptor(GetScriptForDestination(dest), spk_man);
992 
993  UniValue result(UniValue::VOBJ);
994  result.pushKV("address", EncodeDestination(dest));
995  result.pushKV("redeemScript", HexStr(inner.begin(), inner.end()));
996  result.pushKV("descriptor", descriptor->ToString());
997  return result;
998 }
999 
1001 {
1003  int nConf{std::numeric_limits<int>::max()};
1004  std::vector<uint256> txids;
1005  bool fIsWatchonly{false};
1007  {
1008  }
1009 };
1010 
1011 static UniValue ListReceived(const CWallet* const pwallet, const UniValue& params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
1012 {
1013  // Minimum confirmations
1014  int nMinDepth = 1;
1015  if (!params[0].isNull())
1016  nMinDepth = params[0].get_int();
1017 
1018  // Whether to include empty labels
1019  bool fIncludeEmpty = false;
1020  if (!params[1].isNull())
1021  fIncludeEmpty = params[1].get_bool();
1022 
1023  isminefilter filter = ISMINE_SPENDABLE;
1024 
1025  if (ParseIncludeWatchonly(params[2], *pwallet)) {
1026  filter |= ISMINE_WATCH_ONLY;
1027  }
1028 
1029  bool has_filtered_address = false;
1030  CTxDestination filtered_address = CNoDestination();
1031  if (!by_label && params.size() > 3) {
1032  if (!IsValidDestinationString(params[3].get_str())) {
1033  throw JSONRPCError(RPC_WALLET_ERROR, "address_filter parameter was invalid");
1034  }
1035  filtered_address = DecodeDestination(params[3].get_str());
1036  has_filtered_address = true;
1037  }
1038 
1039  // Tally
1040  std::map<CTxDestination, tallyitem> mapTally;
1041  for (const std::pair<const uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
1042  const CWalletTx& wtx = pairWtx.second;
1043 
1044  if (wtx.IsCoinBase() || !pwallet->chain().checkFinalTx(*wtx.tx)) {
1045  continue;
1046  }
1047 
1048  int nDepth = wtx.GetDepthInMainChain();
1049  if (nDepth < nMinDepth)
1050  continue;
1051 
1052  for (const CTxOut& txout : wtx.tx->vout)
1053  {
1054  CTxDestination address;
1055  if (!ExtractDestination(txout.scriptPubKey, address))
1056  continue;
1057 
1058  if (has_filtered_address && !(filtered_address == address)) {
1059  continue;
1060  }
1061 
1062  isminefilter mine = pwallet->IsMine(address);
1063  if(!(mine & filter))
1064  continue;
1065 
1066  tallyitem& item = mapTally[address];
1067  item.nAmount += txout.nValue;
1068  item.nConf = std::min(item.nConf, nDepth);
1069  item.txids.push_back(wtx.GetHash());
1070  if (mine & ISMINE_WATCH_ONLY)
1071  item.fIsWatchonly = true;
1072  }
1073  }
1074 
1075  // Reply
1076  UniValue ret(UniValue::VARR);
1077  std::map<std::string, tallyitem> label_tally;
1078 
1079  // Create m_address_book iterator
1080  // If we aren't filtering, go from begin() to end()
1081  auto start = pwallet->m_address_book.begin();
1082  auto end = pwallet->m_address_book.end();
1083  // If we are filtering, find() the applicable entry
1084  if (has_filtered_address) {
1085  start = pwallet->m_address_book.find(filtered_address);
1086  if (start != end) {
1087  end = std::next(start);
1088  }
1089  }
1090 
1091  for (auto item_it = start; item_it != end; ++item_it)
1092  {
1093  if (item_it->second.IsChange()) continue;
1094  const CTxDestination& address = item_it->first;
1095  const std::string& label = item_it->second.GetLabel();
1096  auto it = mapTally.find(address);
1097  if (it == mapTally.end() && !fIncludeEmpty)
1098  continue;
1099 
1100  CAmount nAmount = 0;
1101  int nConf = std::numeric_limits<int>::max();
1102  bool fIsWatchonly = false;
1103  if (it != mapTally.end())
1104  {
1105  nAmount = (*it).second.nAmount;
1106  nConf = (*it).second.nConf;
1107  fIsWatchonly = (*it).second.fIsWatchonly;
1108  }
1109 
1110  if (by_label)
1111  {
1112  tallyitem& _item = label_tally[label];
1113  _item.nAmount += nAmount;
1114  _item.nConf = std::min(_item.nConf, nConf);
1115  _item.fIsWatchonly = fIsWatchonly;
1116  }
1117  else
1118  {
1119  UniValue obj(UniValue::VOBJ);
1120  if(fIsWatchonly)
1121  obj.pushKV("involvesWatchonly", true);
1122  obj.pushKV("address", EncodeDestination(address));
1123  obj.pushKV("amount", ValueFromAmount(nAmount));
1124  obj.pushKV("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf));
1125  obj.pushKV("label", label);
1126  UniValue transactions(UniValue::VARR);
1127  if (it != mapTally.end())
1128  {
1129  for (const uint256& _item : (*it).second.txids)
1130  {
1131  transactions.push_back(_item.GetHex());
1132  }
1133  }
1134  obj.pushKV("txids", transactions);
1135  ret.push_back(obj);
1136  }
1137  }
1138 
1139  if (by_label)
1140  {
1141  for (const auto& entry : label_tally)
1142  {
1143  CAmount nAmount = entry.second.nAmount;
1144  int nConf = entry.second.nConf;
1145  UniValue obj(UniValue::VOBJ);
1146  if (entry.second.fIsWatchonly)
1147  obj.pushKV("involvesWatchonly", true);
1148  obj.pushKV("amount", ValueFromAmount(nAmount));
1149  obj.pushKV("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf));
1150  obj.pushKV("label", entry.first);
1151  ret.push_back(obj);
1152  }
1153  }
1154 
1155  return ret;
1156 }
1157 
1159 {
1160  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
1161  const CWallet* const pwallet = wallet.get();
1162 
1163  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1164  return NullUniValue;
1165  }
1166 
1167  RPCHelpMan{"listreceivedbyaddress",
1168  "\nList balances by receiving address.\n",
1169  {
1170  {"minconf", RPCArg::Type::NUM, /* default */ "1", "The minimum number of confirmations before payments are included."},
1171  {"include_empty", RPCArg::Type::BOOL, /* default */ "false", "Whether to include addresses that haven't received any payments."},
1172  {"include_watchonly", RPCArg::Type::BOOL, /* default */ "true for watch-only wallets, otherwise false", "Whether to include watch-only addresses (see 'importaddress')"},
1173  {"address_filter", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "If present, only return information on this address."},
1174  },
1175  RPCResult{
1176  RPCResult::Type::ARR, "", "",
1177  {
1178  {RPCResult::Type::OBJ, "", "",
1179  {
1180  {RPCResult::Type::BOOL, "involvesWatchonly", "Only returns true if imported addresses were involved in transaction"},
1181  {RPCResult::Type::STR, "address", "The receiving address"},
1182  {RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " received by the address"},
1183  {RPCResult::Type::NUM, "confirmations", "The number of confirmations of the most recent transaction included"},
1184  {RPCResult::Type::STR, "label", "The label of the receiving address. The default label is \"\""},
1185  {RPCResult::Type::ARR, "txids", "",
1186  {
1187  {RPCResult::Type::STR_HEX, "txid", "The ids of transactions received with the address"},
1188  }},
1189  }},
1190  }
1191  },
1192  RPCExamples{
1193  HelpExampleCli("listreceivedbyaddress", "")
1194  + HelpExampleCli("listreceivedbyaddress", "6 true")
1195  + HelpExampleRpc("listreceivedbyaddress", "6, true, true")
1196  + HelpExampleRpc("listreceivedbyaddress", "6, true, true, \"" + EXAMPLE_ADDRESS[0] + "\"")
1197  },
1198  }.Check(request);
1199 
1200  // Make sure the results are valid at least up to the most recent block
1201  // the user could have gotten from another RPC command prior to now
1202  pwallet->BlockUntilSyncedToCurrentChain();
1203 
1204  LOCK(pwallet->cs_wallet);
1205 
1206  return ListReceived(pwallet, request.params, false);
1207 }
1208 
1210 {
1211  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
1212  const CWallet* const pwallet = wallet.get();
1213 
1214  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1215  return NullUniValue;
1216  }
1217 
1218  RPCHelpMan{"listreceivedbylabel",
1219  "\nList received transactions by label.\n",
1220  {
1221  {"minconf", RPCArg::Type::NUM, /* default */ "1", "The minimum number of confirmations before payments are included."},
1222  {"include_empty", RPCArg::Type::BOOL, /* default */ "false", "Whether to include labels that haven't received any payments."},
1223  {"include_watchonly", RPCArg::Type::BOOL, /* default */ "true for watch-only wallets, otherwise false", "Whether to include watch-only addresses (see 'importaddress')"},
1224  },
1225  RPCResult{
1226  RPCResult::Type::ARR, "", "",
1227  {
1228  {RPCResult::Type::OBJ, "", "",
1229  {
1230  {RPCResult::Type::BOOL, "involvesWatchonly", "Only returns true if imported addresses were involved in transaction"},
1231  {RPCResult::Type::STR_AMOUNT, "amount", "The total amount received by addresses with this label"},
1232  {RPCResult::Type::NUM, "confirmations", "The number of confirmations of the most recent transaction included"},
1233  {RPCResult::Type::STR, "label", "The label of the receiving address. The default label is \"\""},
1234  }},
1235  }
1236  },
1237  RPCExamples{
1238  HelpExampleCli("listreceivedbylabel", "")
1239  + HelpExampleCli("listreceivedbylabel", "6 true")
1240  + HelpExampleRpc("listreceivedbylabel", "6, true, true")
1241  },
1242  }.Check(request);
1243 
1244  // Make sure the results are valid at least up to the most recent block
1245  // the user could have gotten from another RPC command prior to now
1246  pwallet->BlockUntilSyncedToCurrentChain();
1247 
1248  LOCK(pwallet->cs_wallet);
1249 
1250  return ListReceived(pwallet, request.params, true);
1251 }
1252 
1253 static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
1254 {
1255  if (IsValidDestination(dest)) {
1256  entry.pushKV("address", EncodeDestination(dest));
1257  }
1258 }
1259 
1271 static void ListTransactions(const CWallet* const pwallet, const CWalletTx& wtx, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter_ismine, const std::string* filter_label) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
1272 {
1273  CAmount nFee;
1274  std::list<COutputEntry> listReceived;
1275  std::list<COutputEntry> listSent;
1276 
1277  wtx.GetAmounts(listReceived, listSent, nFee, filter_ismine);
1278 
1279  bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY);
1280 
1281  // Sent
1282  if (!filter_label)
1283  {
1284  for (const COutputEntry& s : listSent)
1285  {
1286  UniValue entry(UniValue::VOBJ);
1287  if (involvesWatchonly || (pwallet->IsMine(s.destination) & ISMINE_WATCH_ONLY)) {
1288  entry.pushKV("involvesWatchonly", true);
1289  }
1290  MaybePushAddress(entry, s.destination);
1291  entry.pushKV("category", "send");
1292  entry.pushKV("amount", ValueFromAmount(-s.amount));
1293  const auto* address_book_entry = pwallet->FindAddressBookEntry(s.destination);
1294  if (address_book_entry) {
1295  entry.pushKV("label", address_book_entry->GetLabel());
1296  }
1297  entry.pushKV("vout", s.vout);
1298  entry.pushKV("fee", ValueFromAmount(-nFee));
1299  if (fLong)
1300  WalletTxToJSON(pwallet->chain(), wtx, entry);
1301  entry.pushKV("abandoned", wtx.isAbandoned());
1302  ret.push_back(entry);
1303  }
1304  }
1305 
1306  // Received
1307  if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth) {
1308  for (const COutputEntry& r : listReceived)
1309  {
1310  std::string label;
1311  const auto* address_book_entry = pwallet->FindAddressBookEntry(r.destination);
1312  if (address_book_entry) {
1313  label = address_book_entry->GetLabel();
1314  }
1315  if (filter_label && label != *filter_label) {
1316  continue;
1317  }
1318  UniValue entry(UniValue::VOBJ);
1319  if (involvesWatchonly || (pwallet->IsMine(r.destination) & ISMINE_WATCH_ONLY)) {
1320  entry.pushKV("involvesWatchonly", true);
1321  }
1322  MaybePushAddress(entry, r.destination);
1323  if (wtx.IsCoinBase())
1324  {
1325  if (wtx.GetDepthInMainChain() < 1)
1326  entry.pushKV("category", "orphan");
1327  else if (wtx.IsImmatureCoinBase())
1328  entry.pushKV("category", "immature");
1329  else
1330  entry.pushKV("category", "generate");
1331  }
1332  else
1333  {
1334  entry.pushKV("category", "receive");
1335  }
1336  entry.pushKV("amount", ValueFromAmount(r.amount));
1337  if (address_book_entry) {
1338  entry.pushKV("label", label);
1339  }
1340  entry.pushKV("vout", r.vout);
1341  if (fLong)
1342  WalletTxToJSON(pwallet->chain(), wtx, entry);
1343  ret.push_back(entry);
1344  }
1345  }
1346 }
1347 
1348 static const std::vector<RPCResult> TransactionDescriptionString()
1349 {
1350  return{{RPCResult::Type::NUM, "confirmations", "The number of confirmations for the transaction. Negative confirmations means the\n"
1351  "transaction conflicted that many blocks ago."},
1352  {RPCResult::Type::BOOL, "generated", "Only present if transaction only input is a coinbase one."},
1353  {RPCResult::Type::BOOL, "trusted", "Only present if we consider transaction to be trusted and so safe to spend from."},
1354  {RPCResult::Type::STR_HEX, "blockhash", "The block hash containing the transaction."},
1355  {RPCResult::Type::NUM, "blockheight", "The block height containing the transaction."},
1356  {RPCResult::Type::NUM, "blockindex", "The index of the transaction in the block that includes it."},
1357  {RPCResult::Type::NUM_TIME, "blocktime", "The block time expressed in " + UNIX_EPOCH_TIME + "."},
1358  {RPCResult::Type::STR_HEX, "txid", "The transaction id."},
1359  {RPCResult::Type::ARR, "walletconflicts", "Conflicting transaction ids.",
1360  {
1361  {RPCResult::Type::STR_HEX, "txid", "The transaction id."},
1362  }},
1363  {RPCResult::Type::NUM_TIME, "time", "The transaction time expressed in " + UNIX_EPOCH_TIME + "."},
1364  {RPCResult::Type::NUM_TIME, "timereceived", "The time received expressed in " + UNIX_EPOCH_TIME + "."},
1365  {RPCResult::Type::STR, "comment", "If a comment is associated with the transaction, only present if not empty."},
1366  {RPCResult::Type::STR, "bip125-replaceable", "(\"yes|no|unknown\") Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
1367  "may be unknown for unconfirmed transactions not in the mempool"}};
1368 }
1369 
1371 {
1372  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
1373  const CWallet* const pwallet = wallet.get();
1374 
1375  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1376  return NullUniValue;
1377  }
1378 
1379  RPCHelpMan{"listtransactions",
1380  "\nIf a label name is provided, this will return only incoming transactions paying to addresses with the specified label.\n"
1381  "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions.\n",
1382  {
1383  {"label|dummy", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "If set, should be a valid label name to return only incoming transactions\n"
1384  "with the specified label, or \"*\" to disable filtering and return all transactions."},
1385  {"count", RPCArg::Type::NUM, /* default */ "10", "The number of transactions to return"},
1386  {"skip", RPCArg::Type::NUM, /* default */ "0", "The number of transactions to skip"},
1387  {"include_watchonly", RPCArg::Type::BOOL, /* default */ "true for watch-only wallets, otherwise false", "Include transactions to watch-only addresses (see 'importaddress')"},
1388  },
1389  RPCResult{
1390  RPCResult::Type::ARR, "", "",
1391  {
1392  {RPCResult::Type::OBJ, "", "", Cat(Cat<std::vector<RPCResult>>(
1393  {
1394  {RPCResult::Type::BOOL, "involvesWatchonly", "Only returns true if imported addresses were involved in transaction."},
1395  {RPCResult::Type::STR, "address", "The bitcoin address of the transaction."},
1396  {RPCResult::Type::STR, "category", "The transaction category.\n"
1397  "\"send\" Transactions sent.\n"
1398  "\"receive\" Non-coinbase transactions received.\n"
1399  "\"generate\" Coinbase transactions received with more than 100 confirmations.\n"
1400  "\"immature\" Coinbase transactions received with 100 or fewer confirmations.\n"
1401  "\"orphan\" Orphaned coinbase transactions received."},
1402  {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and is positive\n"
1403  "for all other categories"},
1404  {RPCResult::Type::STR, "label", "A comment for the address/transaction, if any"},
1405  {RPCResult::Type::NUM, "vout", "the vout value"},
1406  {RPCResult::Type::STR_AMOUNT, "fee", "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the\n"
1407  "'send' category of transactions."},
1408  },
1410  {
1411  {RPCResult::Type::BOOL, "abandoned", "'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
1412  "'send' category of transactions."},
1413  })},
1414  }
1415  },
1416  RPCExamples{
1417  "\nList the most recent 10 transactions in the systems\n"
1418  + HelpExampleCli("listtransactions", "") +
1419  "\nList transactions 100 to 120\n"
1420  + HelpExampleCli("listtransactions", "\"*\" 20 100") +
1421  "\nAs a JSON-RPC call\n"
1422  + HelpExampleRpc("listtransactions", "\"*\", 20, 100")
1423  },
1424  }.Check(request);
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  const std::string* filter_label = nullptr;
1431  if (!request.params[0].isNull() && request.params[0].get_str() != "*") {
1432  filter_label = &request.params[0].get_str();
1433  if (filter_label->empty()) {
1434  throw JSONRPCError(RPC_INVALID_PARAMETER, "Label argument must be a valid label name or \"*\".");
1435  }
1436  }
1437  int nCount = 10;
1438  if (!request.params[1].isNull())
1439  nCount = request.params[1].get_int();
1440  int nFrom = 0;
1441  if (!request.params[2].isNull())
1442  nFrom = request.params[2].get_int();
1443  isminefilter filter = ISMINE_SPENDABLE;
1444 
1445  if (ParseIncludeWatchonly(request.params[3], *pwallet)) {
1446  filter |= ISMINE_WATCH_ONLY;
1447  }
1448 
1449  if (nCount < 0)
1450  throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
1451  if (nFrom < 0)
1452  throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
1453 
1454  UniValue ret(UniValue::VARR);
1455 
1456  {
1457  LOCK(pwallet->cs_wallet);
1458 
1459  const CWallet::TxItems & txOrdered = pwallet->wtxOrdered;
1460 
1461  // iterate backwards until we have nCount items to return:
1462  for (CWallet::TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
1463  {
1464  CWalletTx *const pwtx = (*it).second;
1465  ListTransactions(pwallet, *pwtx, 0, true, ret, filter, filter_label);
1466  if ((int)ret.size() >= (nCount+nFrom)) break;
1467  }
1468  }
1469 
1470  // ret is newest to oldest
1471 
1472  if (nFrom > (int)ret.size())
1473  nFrom = ret.size();
1474  if ((nFrom + nCount) > (int)ret.size())
1475  nCount = ret.size() - nFrom;
1476 
1477  const std::vector<UniValue>& txs = ret.getValues();
1478  UniValue result{UniValue::VARR};
1479  result.push_backV({ txs.rend() - nFrom - nCount, txs.rend() - nFrom }); // Return oldest to newest
1480  return result;
1481 }
1482 
1484 {
1485  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
1486 
1487  if (!EnsureWalletIsAvailable(pwallet.get(), request.fHelp)) {
1488  return NullUniValue;
1489  }
1490 
1491  RPCHelpMan{"listsinceblock",
1492  "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted.\n"
1493  "If \"blockhash\" is no longer a part of the main chain, transactions from the fork point onward are included.\n"
1494  "Additionally, if include_removed is set, transactions affecting the wallet which were removed are returned in the \"removed\" array.\n",
1495  {
1496  {"blockhash", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "If set, the block hash to list transactions since, otherwise list all transactions."},
1497  {"target_confirmations", RPCArg::Type::NUM, /* default */ "1", "Return the nth block hash from the main chain. e.g. 1 would mean the best block hash. Note: this is not used as a filter, but only affects [lastblock] in the return value"},
1498  {"include_watchonly", RPCArg::Type::BOOL, /* default */ "true for watch-only wallets, otherwise false", "Include transactions to watch-only addresses (see 'importaddress')"},
1499  {"include_removed", RPCArg::Type::BOOL, /* default */ "true", "Show transactions that were removed due to a reorg in the \"removed\" array\n"
1500  " (not guaranteed to work on pruned nodes)"},
1501  },
1502  RPCResult{
1503  RPCResult::Type::OBJ, "", "",
1504  {
1505  {RPCResult::Type::ARR, "transactions", "",
1506  {
1507  {RPCResult::Type::OBJ, "", "", Cat(Cat<std::vector<RPCResult>>(
1508  {
1509  {RPCResult::Type::BOOL, "involvesWatchonly", "Only returns true if imported addresses were involved in transaction."},
1510  {RPCResult::Type::STR, "address", "The bitcoin address of the transaction."},
1511  {RPCResult::Type::STR, "category", "The transaction category.\n"
1512  "\"send\" Transactions sent.\n"
1513  "\"receive\" Non-coinbase transactions received.\n"
1514  "\"generate\" Coinbase transactions received with more than 100 confirmations.\n"
1515  "\"immature\" Coinbase transactions received with 100 or fewer confirmations.\n"
1516  "\"orphan\" Orphaned coinbase transactions received."},
1517  {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and is positive\n"
1518  "for all other categories"},
1519  {RPCResult::Type::NUM, "vout", "the vout value"},
1520  {RPCResult::Type::STR_AMOUNT, "fee", "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the\n"
1521  "'send' category of transactions."},
1522  },
1524  {
1525  {RPCResult::Type::BOOL, "abandoned", "'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
1526  "'send' category of transactions."},
1527  {RPCResult::Type::STR, "label", "A comment for the address/transaction, if any"},
1528  {RPCResult::Type::STR, "to", "If a comment to is associated with the transaction."},
1529  })},
1530  }},
1531  {RPCResult::Type::ARR, "removed", "<structure is the same as \"transactions\" above, only present if include_removed=true>\n"
1532  "Note: transactions that were re-added in the active chain will appear as-is in this array, and may thus have a positive confirmation count."
1533  , {{RPCResult::Type::ELISION, "", ""},}},
1534  {RPCResult::Type::STR_HEX, "lastblock", "The hash of the block (target_confirmations-1) from the best block on the main chain. This is typically used to feed back into listsinceblock the next time you call it. So you would generally use a target_confirmations of say 6, so you will be continually re-notified of transactions until they've reached 6 confirmations plus any new ones"},
1535  }
1536  },
1537  RPCExamples{
1538  HelpExampleCli("listsinceblock", "")
1539  + HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6")
1540  + HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
1541  },
1542  }.Check(request);
1543 
1544  const CWallet& wallet = *pwallet;
1545  // Make sure the results are valid at least up to the most recent block
1546  // the user could have gotten from another RPC command prior to now
1548 
1549  LOCK(wallet.cs_wallet);
1550 
1551  // The way the 'height' is initialized is just a workaround for the gcc bug #47679 since version 4.6.0.
1552  Optional<int> height = MakeOptional(false, int()); // Height of the specified block or the common ancestor, if the block provided was in a deactivated chain.
1553  Optional<int> altheight; // Height of the specified block, even if it's in a deactivated chain.
1554  int target_confirms = 1;
1555  isminefilter filter = ISMINE_SPENDABLE;
1556 
1557  uint256 blockId;
1558  if (!request.params[0].isNull() && !request.params[0].get_str().empty()) {
1559  blockId = ParseHashV(request.params[0], "blockhash");
1560  height = int{};
1561  altheight = int{};
1562  if (!wallet.chain().findCommonAncestor(blockId, wallet.GetLastBlockHash(), /* ancestor out */ FoundBlock().height(*height), /* blockId out */ FoundBlock().height(*altheight))) {
1563  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1564  }
1565  }
1566 
1567  if (!request.params[1].isNull()) {
1568  target_confirms = request.params[1].get_int();
1569 
1570  if (target_confirms < 1) {
1571  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
1572  }
1573  }
1574 
1575  if (ParseIncludeWatchonly(request.params[2], wallet)) {
1576  filter |= ISMINE_WATCH_ONLY;
1577  }
1578 
1579  bool include_removed = (request.params[3].isNull() || request.params[3].get_bool());
1580 
1581  int depth = height ? wallet.GetLastBlockHeight() + 1 - *height : -1;
1582 
1583  UniValue transactions(UniValue::VARR);
1584 
1585  for (const std::pair<const uint256, CWalletTx>& pairWtx : wallet.mapWallet) {
1586  const CWalletTx& tx = pairWtx.second;
1587 
1588  if (depth == -1 || abs(tx.GetDepthInMainChain()) < depth) {
1589  ListTransactions(&wallet, tx, 0, true, transactions, filter, nullptr /* filter_label */);
1590  }
1591  }
1592 
1593  // when a reorg'd block is requested, we also list any relevant transactions
1594  // in the blocks of the chain that was detached
1595  UniValue removed(UniValue::VARR);
1596  while (include_removed && altheight && *altheight > *height) {
1597  CBlock block;
1598  if (!wallet.chain().findBlock(blockId, FoundBlock().data(block)) || block.IsNull()) {
1599  throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
1600  }
1601  for (const CTransactionRef& tx : block.vtx) {
1602  auto it = wallet.mapWallet.find(tx->GetHash());
1603  if (it != wallet.mapWallet.end()) {
1604  // We want all transactions regardless of confirmation count to appear here,
1605  // even negative confirmation ones, hence the big negative.
1606  ListTransactions(&wallet, it->second, -100000000, true, removed, filter, nullptr /* filter_label */);
1607  }
1608  }
1609  blockId = block.hashPrevBlock;
1610  --*altheight;
1611  }
1612 
1613  uint256 lastblock;
1614  CHECK_NONFATAL(wallet.chain().findAncestorByHeight(wallet.GetLastBlockHash(), wallet.GetLastBlockHeight() + 1 - target_confirms, FoundBlock().hash(lastblock)));
1615 
1616  UniValue ret(UniValue::VOBJ);
1617  ret.pushKV("transactions", transactions);
1618  if (include_removed) ret.pushKV("removed", removed);
1619  ret.pushKV("lastblock", lastblock.GetHex());
1620 
1621  return ret;
1622 }
1623 
1625 {
1626  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
1627  const CWallet* const pwallet = wallet.get();
1628 
1629  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1630  return NullUniValue;
1631  }
1632 
1633  RPCHelpMan{"gettransaction",
1634  "\nGet detailed information about in-wallet transaction <txid>\n",
1635  {
1636  {"txid", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction id"},
1637  {"include_watchonly", RPCArg::Type::BOOL, /* default */ "true for watch-only wallets, otherwise false",
1638  "Whether to include watch-only addresses in balance calculation and details[]"},
1639  {"verbose", RPCArg::Type::BOOL, /* default */ "false",
1640  "Whether to include a `decoded` field containing the decoded transaction (equivalent to RPC decoderawtransaction)"},
1641  },
1642  RPCResult{
1643  RPCResult::Type::OBJ, "", "", Cat(Cat<std::vector<RPCResult>>(
1644  {
1645  {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT},
1646  {RPCResult::Type::STR_AMOUNT, "fee", "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the\n"
1647  "'send' category of transactions."},
1648  },
1650  {
1651  {RPCResult::Type::ARR, "details", "",
1652  {
1653  {RPCResult::Type::OBJ, "", "",
1654  {
1655  {RPCResult::Type::BOOL, "involvesWatchonly", "Only returns true if imported addresses were involved in transaction."},
1656  {RPCResult::Type::STR, "address", "The bitcoin address involved in the transaction."},
1657  {RPCResult::Type::STR, "category", "The transaction category.\n"
1658  "\"send\" Transactions sent.\n"
1659  "\"receive\" Non-coinbase transactions received.\n"
1660  "\"generate\" Coinbase transactions received with more than 100 confirmations.\n"
1661  "\"immature\" Coinbase transactions received with 100 or fewer confirmations.\n"
1662  "\"orphan\" Orphaned coinbase transactions received."},
1663  {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT},
1664  {RPCResult::Type::STR, "label", "A comment for the address/transaction, if any"},
1665  {RPCResult::Type::NUM, "vout", "the vout value"},
1666  {RPCResult::Type::STR_AMOUNT, "fee", "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
1667  "'send' category of transactions."},
1668  {RPCResult::Type::BOOL, "abandoned", "'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
1669  "'send' category of transactions."},
1670  }},
1671  }},
1672  {RPCResult::Type::STR_HEX, "hex", "Raw data for transaction"},
1673  {RPCResult::Type::OBJ, "decoded", "Optional, the decoded transaction (only present when `verbose` is passed)",
1674  {
1675  {RPCResult::Type::ELISION, "", "Equivalent to the RPC decoderawtransaction method, or the RPC getrawtransaction method when `verbose` is passed."},
1676  }},
1677  })
1678  },
1679  RPCExamples{
1680  HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1681  + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true")
1682  + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" false true")
1683  + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1684  },
1685  }.Check(request);
1686 
1687  // Make sure the results are valid at least up to the most recent block
1688  // the user could have gotten from another RPC command prior to now
1689  pwallet->BlockUntilSyncedToCurrentChain();
1690 
1691  LOCK(pwallet->cs_wallet);
1692 
1693  uint256 hash(ParseHashV(request.params[0], "txid"));
1694 
1695  isminefilter filter = ISMINE_SPENDABLE;
1696 
1697  if (ParseIncludeWatchonly(request.params[1], *pwallet)) {
1698  filter |= ISMINE_WATCH_ONLY;
1699  }
1700 
1701  bool verbose = request.params[2].isNull() ? false : request.params[2].get_bool();
1702 
1703  UniValue entry(UniValue::VOBJ);
1704  auto it = pwallet->mapWallet.find(hash);
1705  if (it == pwallet->mapWallet.end()) {
1706  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
1707  }
1708  const CWalletTx& wtx = it->second;
1709 
1710  CAmount nCredit = wtx.GetCredit(filter);
1711  CAmount nDebit = wtx.GetDebit(filter);
1712  CAmount nNet = nCredit - nDebit;
1713  CAmount nFee = (wtx.IsFromMe(filter) ? wtx.tx->GetValueOut() - nDebit : 0);
1714 
1715  entry.pushKV("amount", ValueFromAmount(nNet - nFee));
1716  if (wtx.IsFromMe(filter))
1717  entry.pushKV("fee", ValueFromAmount(nFee));
1718 
1719  WalletTxToJSON(pwallet->chain(), wtx, entry);
1720 
1721  UniValue details(UniValue::VARR);
1722  ListTransactions(pwallet, wtx, 0, false, details, filter, nullptr /* filter_label */);
1723  entry.pushKV("details", details);
1724 
1725  std::string strHex = EncodeHexTx(*wtx.tx, pwallet->chain().rpcSerializationFlags());
1726  entry.pushKV("hex", strHex);
1727 
1728  if (verbose) {
1729  UniValue decoded(UniValue::VOBJ);
1730  TxToUniv(*wtx.tx, uint256(), decoded, false);
1731  entry.pushKV("decoded", decoded);
1732  }
1733 
1734  return entry;
1735 }
1736 
1738 {
1739  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
1740  CWallet* const pwallet = wallet.get();
1741 
1742  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1743  return NullUniValue;
1744  }
1745 
1746  RPCHelpMan{"abandontransaction",
1747  "\nMark in-wallet transaction <txid> as abandoned\n"
1748  "This will mark this transaction and all its in-wallet descendants as abandoned which will allow\n"
1749  "for their inputs to be respent. It can be used to replace \"stuck\" or evicted transactions.\n"
1750  "It only works on transactions which are not included in a block and are not currently in the mempool.\n"
1751  "It has no effect on transactions which are already abandoned.\n",
1752  {
1753  {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
1754  },
1756  RPCExamples{
1757  HelpExampleCli("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1758  + HelpExampleRpc("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1759  },
1760  }.Check(request);
1761 
1762  // Make sure the results are valid at least up to the most recent block
1763  // the user could have gotten from another RPC command prior to now
1764  pwallet->BlockUntilSyncedToCurrentChain();
1765 
1766  LOCK(pwallet->cs_wallet);
1767 
1768  uint256 hash(ParseHashV(request.params[0], "txid"));
1769 
1770  if (!pwallet->mapWallet.count(hash)) {
1771  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
1772  }
1773  if (!pwallet->AbandonTransaction(hash)) {
1774  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not eligible for abandonment");
1775  }
1776 
1777  return NullUniValue;
1778 }
1779 
1780 
1781 static UniValue backupwallet(const JSONRPCRequest& request)
1782 {
1783  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
1784  const CWallet* const pwallet = wallet.get();
1785 
1786  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1787  return NullUniValue;
1788  }
1789 
1790  RPCHelpMan{"backupwallet",
1791  "\nSafely copies current wallet file to destination, which can be a directory or a path with filename.\n",
1792  {
1793  {"destination", RPCArg::Type::STR, RPCArg::Optional::NO, "The destination directory or file"},
1794  },
1796  RPCExamples{
1797  HelpExampleCli("backupwallet", "\"backup.dat\"")
1798  + HelpExampleRpc("backupwallet", "\"backup.dat\"")
1799  },
1800  }.Check(request);
1801 
1802  // Make sure the results are valid at least up to the most recent block
1803  // the user could have gotten from another RPC command prior to now
1804  pwallet->BlockUntilSyncedToCurrentChain();
1805 
1806  LOCK(pwallet->cs_wallet);
1807 
1808  std::string strDest = request.params[0].get_str();
1809  if (!pwallet->BackupWallet(strDest)) {
1810  throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
1811  }
1812 
1813  return NullUniValue;
1814 }
1815 
1816 
1817 static UniValue keypoolrefill(const JSONRPCRequest& request)
1818 {
1819  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
1820  CWallet* const pwallet = wallet.get();
1821 
1822  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1823  return NullUniValue;
1824  }
1825 
1826  RPCHelpMan{"keypoolrefill",
1827  "\nFills the keypool."+
1829  {
1830  {"newsize", RPCArg::Type::NUM, /* default */ "100", "The new keypool size"},
1831  },
1833  RPCExamples{
1834  HelpExampleCli("keypoolrefill", "")
1835  + HelpExampleRpc("keypoolrefill", "")
1836  },
1837  }.Check(request);
1838 
1839  if (pwallet->IsLegacy() && pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
1840  throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
1841  }
1842 
1843  LOCK(pwallet->cs_wallet);
1844 
1845  // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
1846  unsigned int kpSize = 0;
1847  if (!request.params[0].isNull()) {
1848  if (request.params[0].get_int() < 0)
1849  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
1850  kpSize = (unsigned int)request.params[0].get_int();
1851  }
1852 
1853  EnsureWalletIsUnlocked(pwallet);
1854  pwallet->TopUpKeyPool(kpSize);
1855 
1856  if (pwallet->GetKeyPoolSize() < kpSize) {
1857  throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
1858  }
1859 
1860  return NullUniValue;
1861 }
1862 
1863 
1865 {
1866  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
1867  CWallet* const pwallet = wallet.get();
1868 
1869  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1870  return NullUniValue;
1871  }
1872 
1873  RPCHelpMan{"walletpassphrase",
1874  "\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
1875  "This is needed prior to performing transactions related to private keys such as sending bitcoins\n"
1876  "\nNote:\n"
1877  "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
1878  "time that overrides the old one.\n",
1879  {
1880  {"passphrase", RPCArg::Type::STR, RPCArg::Optional::NO, "The wallet passphrase"},
1881  {"timeout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The time to keep the decryption key in seconds; capped at 100000000 (~3 years)."},
1882  },
1884  RPCExamples{
1885  "\nUnlock the wallet for 60 seconds\n"
1886  + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
1887  "\nLock the wallet again (before 60 seconds)\n"
1888  + HelpExampleCli("walletlock", "") +
1889  "\nAs a JSON-RPC call\n"
1890  + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
1891  },
1892  }.Check(request);
1893 
1894  int64_t nSleepTime;
1895  int64_t relock_time;
1896  // Prevent concurrent calls to walletpassphrase with the same wallet.
1897  LOCK(pwallet->m_unlock_mutex);
1898  {
1899  LOCK(pwallet->cs_wallet);
1900 
1901  if (!pwallet->IsCrypted()) {
1902  throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1903  }
1904 
1905  // Note that the walletpassphrase is stored in request.params[0] which is not mlock()ed
1906  SecureString strWalletPass;
1907  strWalletPass.reserve(100);
1908  // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1909  // Alternately, find a way to make request.params[0] mlock()'d to begin with.
1910  strWalletPass = request.params[0].get_str().c_str();
1911 
1912  // Get the timeout
1913  nSleepTime = request.params[1].get_int64();
1914  // Timeout cannot be negative, otherwise it will relock immediately
1915  if (nSleepTime < 0) {
1916  throw JSONRPCError(RPC_INVALID_PARAMETER, "Timeout cannot be negative.");
1917  }
1918  // Clamp timeout
1919  constexpr int64_t MAX_SLEEP_TIME = 100000000; // larger values trigger a macos/libevent bug?
1920  if (nSleepTime > MAX_SLEEP_TIME) {
1921  nSleepTime = MAX_SLEEP_TIME;
1922  }
1923 
1924  if (strWalletPass.empty()) {
1925  throw JSONRPCError(RPC_INVALID_PARAMETER, "passphrase can not be empty");
1926  }
1927 
1928  if (!pwallet->Unlock(strWalletPass)) {
1929  throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
1930  }
1931 
1932  pwallet->TopUpKeyPool();
1933 
1934  pwallet->nRelockTime = GetTime() + nSleepTime;
1935  relock_time = pwallet->nRelockTime;
1936  }
1937 
1938  // rpcRunLater must be called without cs_wallet held otherwise a deadlock
1939  // can occur. The deadlock would happen when RPCRunLater removes the
1940  // previous timer (and waits for the callback to finish if already running)
1941  // and the callback locks cs_wallet.
1942  AssertLockNotHeld(wallet->cs_wallet);
1943  // Keep a weak pointer to the wallet so that it is possible to unload the
1944  // wallet before the following callback is called. If a valid shared pointer
1945  // is acquired in the callback then the wallet is still loaded.
1946  std::weak_ptr<CWallet> weak_wallet = wallet;
1947  pwallet->chain().rpcRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), [weak_wallet, relock_time] {
1948  if (auto shared_wallet = weak_wallet.lock()) {
1949  LOCK(shared_wallet->cs_wallet);
1950  // Skip if this is not the most recent rpcRunLater callback.
1951  if (shared_wallet->nRelockTime != relock_time) return;
1952  shared_wallet->Lock();
1953  shared_wallet->nRelockTime = 0;
1954  }
1955  }, nSleepTime);
1956 
1957  return NullUniValue;
1958 }
1959 
1960 
1962 {
1963  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
1964  CWallet* const pwallet = wallet.get();
1965 
1966  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1967  return NullUniValue;
1968  }
1969 
1970  RPCHelpMan{"walletpassphrasechange",
1971  "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n",
1972  {
1973  {"oldpassphrase", RPCArg::Type::STR, RPCArg::Optional::NO, "The current passphrase"},
1974  {"newpassphrase", RPCArg::Type::STR, RPCArg::Optional::NO, "The new passphrase"},
1975  },
1977  RPCExamples{
1978  HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
1979  + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
1980  },
1981  }.Check(request);
1982 
1983  LOCK(pwallet->cs_wallet);
1984 
1985  if (!pwallet->IsCrypted()) {
1986  throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1987  }
1988 
1989  // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1990  // Alternately, find a way to make request.params[0] mlock()'d to begin with.
1991  SecureString strOldWalletPass;
1992  strOldWalletPass.reserve(100);
1993  strOldWalletPass = request.params[0].get_str().c_str();
1994 
1995  SecureString strNewWalletPass;
1996  strNewWalletPass.reserve(100);
1997  strNewWalletPass = request.params[1].get_str().c_str();
1998 
1999  if (strOldWalletPass.empty() || strNewWalletPass.empty()) {
2000  throw JSONRPCError(RPC_INVALID_PARAMETER, "passphrase can not be empty");
2001  }
2002 
2003  if (!pwallet->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass)) {
2004  throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
2005  }
2006 
2007  return NullUniValue;
2008 }
2009 
2010 
2011 static UniValue walletlock(const JSONRPCRequest& request)
2012 {
2013  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
2014  CWallet* const pwallet = wallet.get();
2015 
2016  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2017  return NullUniValue;
2018  }
2019 
2020  RPCHelpMan{"walletlock",
2021  "\nRemoves the wallet encryption key from memory, locking the wallet.\n"
2022  "After calling this method, you will need to call walletpassphrase again\n"
2023  "before being able to call any methods which require the wallet to be unlocked.\n",
2024  {},
2026  RPCExamples{
2027  "\nSet the passphrase for 2 minutes to perform a transaction\n"
2028  + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +
2029  "\nPerform a send (requires passphrase set)\n"
2030  + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 1.0") +
2031  "\nClear the passphrase since we are done before 2 minutes is up\n"
2032  + HelpExampleCli("walletlock", "") +
2033  "\nAs a JSON-RPC call\n"
2034  + HelpExampleRpc("walletlock", "")
2035  },
2036  }.Check(request);
2037 
2038  LOCK(pwallet->cs_wallet);
2039 
2040  if (!pwallet->IsCrypted()) {
2041  throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");
2042  }
2043 
2044  pwallet->Lock();
2045  pwallet->nRelockTime = 0;
2046 
2047  return NullUniValue;
2048 }
2049 
2050 
2051 static UniValue encryptwallet(const JSONRPCRequest& request)
2052 {
2053  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
2054  CWallet* const pwallet = wallet.get();
2055 
2056  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2057  return NullUniValue;
2058  }
2059 
2060  RPCHelpMan{"encryptwallet",
2061  "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
2062  "After this, any calls that interact with private keys such as sending or signing \n"
2063  "will require the passphrase to be set prior the making these calls.\n"
2064  "Use the walletpassphrase call for this, and then walletlock call.\n"
2065  "If the wallet is already encrypted, use the walletpassphrasechange call.\n",
2066  {
2067  {"passphrase", RPCArg::Type::STR, RPCArg::Optional::NO, "The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long."},
2068  },
2069  RPCResult{RPCResult::Type::STR, "", "A string with further instructions"},
2070  RPCExamples{
2071  "\nEncrypt your wallet\n"
2072  + HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
2073  "\nNow set the passphrase to use the wallet, such as for signing or sending bitcoin\n"
2074  + HelpExampleCli("walletpassphrase", "\"my pass phrase\"") +
2075  "\nNow we can do something like sign\n"
2076  + HelpExampleCli("signmessage", "\"address\" \"test message\"") +
2077  "\nNow lock the wallet again by removing the passphrase\n"
2078  + HelpExampleCli("walletlock", "") +
2079  "\nAs a JSON-RPC call\n"
2080  + HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
2081  },
2082  }.Check(request);
2083 
2084  LOCK(pwallet->cs_wallet);
2085 
2087  throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: wallet does not contain private keys, nothing to encrypt.");
2088  }
2089 
2090  if (pwallet->IsCrypted()) {
2091  throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
2092  }
2093 
2094  // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
2095  // Alternately, find a way to make request.params[0] mlock()'d to begin with.
2096  SecureString strWalletPass;
2097  strWalletPass.reserve(100);
2098  strWalletPass = request.params[0].get_str().c_str();
2099 
2100  if (strWalletPass.empty()) {
2101  throw JSONRPCError(RPC_INVALID_PARAMETER, "passphrase can not be empty");
2102  }
2103 
2104  if (!pwallet->EncryptWallet(strWalletPass)) {
2105  throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet.");
2106  }
2107 
2108  return "wallet encrypted; The keypool has been flushed and a new HD seed was generated (if you are using HD). You need to make a new backup.";
2109 }
2110 
2111 static UniValue lockunspent(const JSONRPCRequest& request)
2112 {
2113  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
2114  CWallet* const pwallet = wallet.get();
2115 
2116  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2117  return NullUniValue;
2118  }
2119 
2120  RPCHelpMan{"lockunspent",
2121  "\nUpdates list of temporarily unspendable outputs.\n"
2122  "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
2123  "If no transaction outputs are specified when unlocking then all current locked transaction outputs are unlocked.\n"
2124  "A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n"
2125  "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
2126  "is always cleared (by virtue of process exit) when a node stops or fails.\n"
2127  "Also see the listunspent call\n",
2128  {
2129  {"unlock", RPCArg::Type::BOOL, RPCArg::Optional::NO, "Whether to unlock (true) or lock (false) the specified transactions"},
2130  {"transactions", RPCArg::Type::ARR, /* default */ "empty array", "The transaction outputs and within each, the txid (string) vout (numeric).",
2131  {
2133  {
2134  {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
2135  {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
2136  },
2137  },
2138  },
2139  },
2140  },
2141  RPCResult{
2142  RPCResult::Type::BOOL, "", "Whether the command was successful or not"
2143  },
2144  RPCExamples{
2145  "\nList the unspent transactions\n"
2146  + HelpExampleCli("listunspent", "") +
2147  "\nLock an unspent transaction\n"
2148  + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2149  "\nList the locked transactions\n"
2150  + HelpExampleCli("listlockunspent", "") +
2151  "\nUnlock the transaction again\n"
2152  + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2153  "\nAs a JSON-RPC call\n"
2154  + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
2155  },
2156  }.Check(request);
2157 
2158  // Make sure the results are valid at least up to the most recent block
2159  // the user could have gotten from another RPC command prior to now
2160  pwallet->BlockUntilSyncedToCurrentChain();
2161 
2162  LOCK(pwallet->cs_wallet);
2163 
2165 
2166  bool fUnlock = request.params[0].get_bool();
2167 
2168  if (request.params[1].isNull()) {
2169  if (fUnlock)
2170  pwallet->UnlockAllCoins();
2171  return true;
2172  }
2173 
2175 
2176  const UniValue& output_params = request.params[1];
2177 
2178  // Create and validate the COutPoints first.
2179 
2180  std::vector<COutPoint> outputs;
2181  outputs.reserve(output_params.size());
2182 
2183  for (unsigned int idx = 0; idx < output_params.size(); idx++) {
2184  const UniValue& o = output_params[idx].get_obj();
2185 
2186  RPCTypeCheckObj(o,
2187  {
2188  {"txid", UniValueType(UniValue::VSTR)},
2189  {"vout", UniValueType(UniValue::VNUM)},
2190  });
2191 
2192  const uint256 txid(ParseHashO(o, "txid"));
2193  const int nOutput = find_value(o, "vout").get_int();
2194  if (nOutput < 0) {
2195  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
2196  }
2197 
2198  const COutPoint outpt(txid, nOutput);
2199 
2200  const auto it = pwallet->mapWallet.find(outpt.hash);
2201  if (it == pwallet->mapWallet.end()) {
2202  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, unknown transaction");
2203  }
2204 
2205  const CWalletTx& trans = it->second;
2206 
2207  if (outpt.n >= trans.tx->vout.size()) {
2208  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout index out of bounds");
2209  }
2210 
2211  if (pwallet->IsSpent(outpt.hash, outpt.n)) {
2212  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected unspent output");
2213  }
2214 
2215  const bool is_locked = pwallet->IsLockedCoin(outpt.hash, outpt.n);
2216 
2217  if (fUnlock && !is_locked) {
2218  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected locked output");
2219  }
2220 
2221  if (!fUnlock && is_locked) {
2222  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, output already locked");
2223  }
2224 
2225  outputs.push_back(outpt);
2226  }
2227 
2228  // Atomically set (un)locked status for the outputs.
2229  for (const COutPoint& outpt : outputs) {
2230  if (fUnlock) pwallet->UnlockCoin(outpt);
2231  else pwallet->LockCoin(outpt);
2232  }
2233 
2234  return true;
2235 }
2236 
2238 {
2239  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
2240  const CWallet* const pwallet = wallet.get();
2241 
2242  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2243  return NullUniValue;
2244  }
2245 
2246  RPCHelpMan{"listlockunspent",
2247  "\nReturns list of temporarily unspendable outputs.\n"
2248  "See the lockunspent call to lock and unlock transactions for spending.\n",
2249  {},
2250  RPCResult{
2251  RPCResult::Type::ARR, "", "",
2252  {
2253  {RPCResult::Type::OBJ, "", "",
2254  {
2255  {RPCResult::Type::STR_HEX, "txid", "The transaction id locked"},
2256  {RPCResult::Type::NUM, "vout", "The vout value"},
2257  }},
2258  }
2259  },
2260  RPCExamples{
2261  "\nList the unspent transactions\n"
2262  + HelpExampleCli("listunspent", "") +
2263  "\nLock an unspent transaction\n"
2264  + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2265  "\nList the locked transactions\n"
2266  + HelpExampleCli("listlockunspent", "") +
2267  "\nUnlock the transaction again\n"
2268  + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2269  "\nAs a JSON-RPC call\n"
2270  + HelpExampleRpc("listlockunspent", "")
2271  },
2272  }.Check(request);
2273 
2274  LOCK(pwallet->cs_wallet);
2275 
2276  std::vector<COutPoint> vOutpts;
2277  pwallet->ListLockedCoins(vOutpts);
2278 
2279  UniValue ret(UniValue::VARR);
2280 
2281  for (const COutPoint& outpt : vOutpts) {
2283 
2284  o.pushKV("txid", outpt.hash.GetHex());
2285  o.pushKV("vout", (int)outpt.n);
2286  ret.push_back(o);
2287  }
2288 
2289  return ret;
2290 }
2291 
2292 static UniValue settxfee(const JSONRPCRequest& request)
2293 {
2294  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
2295  CWallet* const pwallet = wallet.get();
2296 
2297  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2298  return NullUniValue;
2299  }
2300 
2301  RPCHelpMan{"settxfee",
2302  "\nSet the transaction fee per kB for this wallet. Overrides the global -paytxfee command line parameter.\n"
2303  "Can be deactivated by passing 0 as the fee. In that case automatic fee selection will be used by default.\n",
2304  {
2305  {"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The transaction fee in " + CURRENCY_UNIT + "/kB"},
2306  },
2307  RPCResult{
2308  RPCResult::Type::BOOL, "", "Returns true if successful"
2309  },
2310  RPCExamples{
2311  HelpExampleCli("settxfee", "0.00001")
2312  + HelpExampleRpc("settxfee", "0.00001")
2313  },
2314  }.Check(request);
2315 
2316  LOCK(pwallet->cs_wallet);
2317 
2318  CAmount nAmount = AmountFromValue(request.params[0]);
2319  CFeeRate tx_fee_rate(nAmount, 1000);
2320  CFeeRate max_tx_fee_rate(pwallet->m_default_max_tx_fee, 1000);
2321  if (tx_fee_rate == CFeeRate(0)) {
2322  // automatic selection
2323  } else if (tx_fee_rate < pwallet->chain().relayMinFee()) {
2324  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("txfee cannot be less than min relay tx fee (%s)", pwallet->chain().relayMinFee().ToString()));
2325  } else if (tx_fee_rate < pwallet->m_min_fee) {
2326  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("txfee cannot be less than wallet min fee (%s)", pwallet->m_min_fee.ToString()));
2327  } else if (tx_fee_rate > max_tx_fee_rate) {
2328  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("txfee cannot be more than wallet max tx fee (%s)", max_tx_fee_rate.ToString()));
2329  }
2330 
2331  pwallet->m_pay_tx_fee = tx_fee_rate;
2332  return true;
2333 }
2334 
2335 static UniValue getbalances(const JSONRPCRequest& request)
2336 {
2337  std::shared_ptr<CWallet> const rpc_wallet = GetWalletForJSONRPCRequest(request);
2338  if (!EnsureWalletIsAvailable(rpc_wallet.get(), request.fHelp)) {
2339  return NullUniValue;
2340  }
2341  CWallet& wallet = *rpc_wallet;
2342 
2343  RPCHelpMan{
2344  "getbalances",
2345  "Returns an object with all balances in " + CURRENCY_UNIT + ".\n",
2346  {},
2347  RPCResult{
2348  RPCResult::Type::OBJ, "", "",
2349  {
2350  {RPCResult::Type::OBJ, "mine", "balances from outputs that the wallet can sign",
2351  {
2352  {RPCResult::Type::STR_AMOUNT, "trusted", "trusted balance (outputs created by the wallet or confirmed outputs)"},
2353  {RPCResult::Type::STR_AMOUNT, "untrusted_pending", "untrusted pending balance (outputs created by others that are in the mempool)"},
2354  {RPCResult::Type::STR_AMOUNT, "immature", "balance from immature coinbase outputs"},
2355  {RPCResult::Type::STR_AMOUNT, "used", "(only present if avoid_reuse is set) balance from coins sent to addresses that were previously spent from (potentially privacy violating)"},
2356  }},
2357  {RPCResult::Type::OBJ, "watchonly", "watchonly balances (not present if wallet does not watch anything)",
2358  {
2359  {RPCResult::Type::STR_AMOUNT, "trusted", "trusted balance (outputs created by the wallet or confirmed outputs)"},
2360  {RPCResult::Type::STR_AMOUNT, "untrusted_pending", "untrusted pending balance (outputs created by others that are in the mempool)"},
2361  {RPCResult::Type::STR_AMOUNT, "immature", "balance from immature coinbase outputs"},
2362  }},
2363  }
2364  },
2365  RPCExamples{
2366  HelpExampleCli("getbalances", "") +
2367  HelpExampleRpc("getbalances", "")},
2368  }.Check(request);
2369 
2370  // Make sure the results are valid at least up to the most recent block
2371  // the user could have gotten from another RPC command prior to now
2373 
2374  LOCK(wallet.cs_wallet);
2375 
2376  const auto bal = wallet.GetBalance();
2377  UniValue balances{UniValue::VOBJ};
2378  {
2379  UniValue balances_mine{UniValue::VOBJ};
2380  balances_mine.pushKV("trusted", ValueFromAmount(bal.m_mine_trusted));
2381  balances_mine.pushKV("untrusted_pending", ValueFromAmount(bal.m_mine_untrusted_pending));
2382  balances_mine.pushKV("immature", ValueFromAmount(bal.m_mine_immature));
2384  // If the AVOID_REUSE flag is set, bal has been set to just the un-reused address balance. Get
2385  // the total balance, and then subtract bal to get the reused address balance.
2386  const auto full_bal = wallet.GetBalance(0, false);
2387  balances_mine.pushKV("used", ValueFromAmount(full_bal.m_mine_trusted + full_bal.m_mine_untrusted_pending - bal.m_mine_trusted - bal.m_mine_untrusted_pending));
2388  }
2389  balances.pushKV("mine", balances_mine);
2390  }
2391  auto spk_man = wallet.GetLegacyScriptPubKeyMan();
2392  if (spk_man && spk_man->HaveWatchOnly()) {
2393  UniValue balances_watchonly{UniValue::VOBJ};
2394  balances_watchonly.pushKV("trusted", ValueFromAmount(bal.m_watchonly_trusted));
2395  balances_watchonly.pushKV("untrusted_pending", ValueFromAmount(bal.m_watchonly_untrusted_pending));
2396  balances_watchonly.pushKV("immature", ValueFromAmount(bal.m_watchonly_immature));
2397  balances.pushKV("watchonly", balances_watchonly);
2398  }
2399  return balances;
2400 }
2401 
2402 static UniValue getwalletinfo(const JSONRPCRequest& request)
2403 {
2404  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
2405  const CWallet* const pwallet = wallet.get();
2406 
2407  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2408  return NullUniValue;
2409  }
2410 
2411  RPCHelpMan{"getwalletinfo",
2412  "Returns an object containing various wallet state info.\n",
2413  {},
2414  RPCResult{
2415  RPCResult::Type::OBJ, "", "",
2416  {
2417  {
2418  {RPCResult::Type::STR, "walletname", "the wallet name"},
2419  {RPCResult::Type::NUM, "walletversion", "the wallet version"},
2420  {RPCResult::Type::STR_AMOUNT, "balance", "DEPRECATED. Identical to getbalances().mine.trusted"},
2421  {RPCResult::Type::STR_AMOUNT, "unconfirmed_balance", "DEPRECATED. Identical to getbalances().mine.untrusted_pending"},
2422  {RPCResult::Type::STR_AMOUNT, "immature_balance", "DEPRECATED. Identical to getbalances().mine.immature"},
2423  {RPCResult::Type::NUM, "txcount", "the total number of transactions in the wallet"},
2424  {RPCResult::Type::NUM_TIME, "keypoololdest", "the " + UNIX_EPOCH_TIME + " of the oldest pre-generated key in the key pool. Legacy wallets only."},
2425  {RPCResult::Type::NUM, "keypoolsize", "how many new keys are pre-generated (only counts external keys)"},
2426  {RPCResult::Type::NUM, "keypoolsize_hd_internal", "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)"},
2427  {RPCResult::Type::NUM_TIME, "unlocked_until", "the " + UNIX_EPOCH_TIME + " until which the wallet is unlocked for transfers, or 0 if the wallet is locked"},
2428  {RPCResult::Type::STR_AMOUNT, "paytxfee", "the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB"},
2429  {RPCResult::Type::STR_HEX, "hdseedid", /* optional */ true, "the Hash160 of the HD seed (only present when HD is enabled)"},
2430  {RPCResult::Type::BOOL, "private_keys_enabled", "false if privatekeys are disabled for this wallet (enforced watch-only wallet)"},
2431  {RPCResult::Type::BOOL, "avoid_reuse", "whether this wallet tracks clean/dirty coins in terms of reuse"},
2432  {RPCResult::Type::OBJ, "scanning", "current scanning details, or false if no scan is in progress",
2433  {
2434  {RPCResult::Type::NUM, "duration", "elapsed seconds since scan start"},
2435  {RPCResult::Type::NUM, "progress", "scanning progress percentage [0.0, 1.0]"},
2436  }},
2437  {RPCResult::Type::BOOL, "descriptors", "whether this wallet uses descriptors for scriptPubKey management"},
2438  }},
2439  },
2440  RPCExamples{
2441  HelpExampleCli("getwalletinfo", "")
2442  + HelpExampleRpc("getwalletinfo", "")
2443  },
2444  }.Check(request);
2445 
2446  // Make sure the results are valid at least up to the most recent block
2447  // the user could have gotten from another RPC command prior to now
2448  pwallet->BlockUntilSyncedToCurrentChain();
2449 
2450  LOCK(pwallet->cs_wallet);
2451 
2452  UniValue obj(UniValue::VOBJ);
2453 
2454  size_t kpExternalSize = pwallet->KeypoolCountExternalKeys();
2455  const auto bal = pwallet->GetBalance();
2456  int64_t kp_oldest = pwallet->GetOldestKeyPoolTime();
2457  obj.pushKV("walletname", pwallet->GetName());
2458  obj.pushKV("walletversion", pwallet->GetVersion());
2459  obj.pushKV("balance", ValueFromAmount(bal.m_mine_trusted));
2460  obj.pushKV("unconfirmed_balance", ValueFromAmount(bal.m_mine_untrusted_pending));
2461  obj.pushKV("immature_balance", ValueFromAmount(bal.m_mine_immature));
2462  obj.pushKV("txcount", (int)pwallet->mapWallet.size());
2463  if (kp_oldest > 0) {
2464  obj.pushKV("keypoololdest", kp_oldest);
2465  }
2466  obj.pushKV("keypoolsize", (int64_t)kpExternalSize);
2467 
2468  LegacyScriptPubKeyMan* spk_man = pwallet->GetLegacyScriptPubKeyMan();
2469  if (spk_man) {
2470  CKeyID seed_id = spk_man->GetHDChain().seed_id;
2471  if (!seed_id.IsNull()) {
2472  obj.pushKV("hdseedid", seed_id.GetHex());
2473  }
2474  }
2475 
2476  if (pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) {
2477  obj.pushKV("keypoolsize_hd_internal", (int64_t)(pwallet->GetKeyPoolSize() - kpExternalSize));
2478  }
2479  if (pwallet->IsCrypted()) {
2480  obj.pushKV("unlocked_until", pwallet->nRelockTime);
2481  }
2482  obj.pushKV("paytxfee", ValueFromAmount(pwallet->m_pay_tx_fee.GetFeePerK()));
2483  obj.pushKV("private_keys_enabled", !pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
2484  obj.pushKV("avoid_reuse", pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE));
2485  if (pwallet->IsScanning()) {
2486  UniValue scanning(UniValue::VOBJ);
2487  scanning.pushKV("duration", pwallet->ScanningDuration() / 1000);
2488  scanning.pushKV("progress", pwallet->ScanningProgress());
2489  obj.pushKV("scanning", scanning);
2490  } else {
2491  obj.pushKV("scanning", false);
2492  }
2493  obj.pushKV("descriptors", pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
2494  return obj;
2495 }
2496 
2497 static UniValue listwalletdir(const JSONRPCRequest& request)
2498 {
2499  RPCHelpMan{"listwalletdir",
2500  "Returns a list of wallets in the wallet directory.\n",
2501  {},
2502  RPCResult{
2503  RPCResult::Type::OBJ, "", "",
2504  {
2505  {RPCResult::Type::ARR, "wallets", "",
2506  {
2507  {RPCResult::Type::OBJ, "", "",
2508  {
2509  {RPCResult::Type::STR, "name", "The wallet name"},
2510  }},
2511  }},
2512  }
2513  },
2514  RPCExamples{
2515  HelpExampleCli("listwalletdir", "")
2516  + HelpExampleRpc("listwalletdir", "")
2517  },
2518  }.Check(request);
2519 
2520  UniValue wallets(UniValue::VARR);
2521  for (const auto& path : ListWalletDir()) {
2522  UniValue wallet(UniValue::VOBJ);
2523  wallet.pushKV("name", path.string());
2524  wallets.push_back(wallet);
2525  }
2526 
2527  UniValue result(UniValue::VOBJ);
2528  result.pushKV("wallets", wallets);
2529  return result;
2530 }
2531 
2532 static UniValue listwallets(const JSONRPCRequest& request)
2533 {
2534  RPCHelpMan{"listwallets",
2535  "Returns a list of currently loaded wallets.\n"
2536  "For full information on the wallet, use \"getwalletinfo\"\n",
2537  {},
2538  RPCResult{
2539  RPCResult::Type::ARR, "", "",
2540  {
2541  {RPCResult::Type::STR, "walletname", "the wallet name"},
2542  }
2543  },
2544  RPCExamples{
2545  HelpExampleCli("listwallets", "")
2546  + HelpExampleRpc("listwallets", "")
2547  },
2548  }.Check(request);
2549 
2550  UniValue obj(UniValue::VARR);
2551 
2552  for (const std::shared_ptr<CWallet>& wallet : GetWallets()) {
2553  if (!EnsureWalletIsAvailable(wallet.get(), request.fHelp)) {
2554  return NullUniValue;
2555  }
2556 
2557  LOCK(wallet->cs_wallet);
2558 
2559  obj.push_back(wallet->GetName());
2560  }
2561 
2562  return obj;
2563 }
2564 
2565 static UniValue loadwallet(const JSONRPCRequest& request)
2566 {
2567  RPCHelpMan{"loadwallet",
2568  "\nLoads a wallet from a wallet file or directory."
2569  "\nNote that all wallet command-line options used when starting bitcoind will be"
2570  "\napplied to the new wallet (eg -zapwallettxes, rescan, etc).\n",
2571  {
2572  {"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The wallet directory or .dat file."},
2573  },
2574  RPCResult{
2575  RPCResult::Type::OBJ, "", "",
2576  {
2577  {RPCResult::Type::STR, "name", "The wallet name if loaded successfully."},
2578  {RPCResult::Type::STR, "warning", "Warning message if wallet was not loaded cleanly."},
2579  }
2580  },
2581  RPCExamples{
2582  HelpExampleCli("loadwallet", "\"test.dat\"")
2583  + HelpExampleRpc("loadwallet", "\"test.dat\"")
2584  },
2585  }.Check(request);
2586 
2587  WalletLocation location(request.params[0].get_str());
2588 
2589  if (!location.Exists()) {
2590  throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Wallet " + location.GetName() + " not found.");
2591  } else if (fs::is_directory(location.GetPath())) {
2592  // The given filename is a directory. Check that there's a wallet.dat file.
2593  fs::path wallet_dat_file = location.GetPath() / "wallet.dat";
2594  if (fs::symlink_status(wallet_dat_file).type() == fs::file_not_found) {
2595  throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Directory " + location.GetName() + " does not contain a wallet.dat file.");
2596  }
2597  }
2598 
2600  std::vector<bilingual_str> warnings;
2601  std::shared_ptr<CWallet> const wallet = LoadWallet(*g_rpc_chain, location, error, warnings);
2602  if (!wallet) throw JSONRPCError(RPC_WALLET_ERROR, error.original);
2603 
2604  UniValue obj(UniValue::VOBJ);
2605  obj.pushKV("name", wallet->GetName());
2606  obj.pushKV("warning", Join(warnings, Untranslated("\n")).original);
2607 
2608  return obj;
2609 }
2610 
2611 static UniValue setwalletflag(const JSONRPCRequest& request)
2612 {
2613  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
2614  CWallet* const pwallet = wallet.get();
2615 
2616  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2617  return NullUniValue;
2618  }
2619 
2620  std::string flags = "";
2621  for (auto& it : WALLET_FLAG_MAP)
2622  if (it.second & MUTABLE_WALLET_FLAGS)
2623  flags += (flags == "" ? "" : ", ") + it.first;
2624  RPCHelpMan{"setwalletflag",
2625  "\nChange the state of the given wallet flag for a wallet.\n",
2626  {
2627  {"flag", RPCArg::Type::STR, RPCArg::Optional::NO, "The name of the flag to change. Current available flags: " + flags},
2628  {"value", RPCArg::Type::BOOL, /* default */ "true", "The new state."},
2629  },
2630  RPCResult{
2631  RPCResult::Type::OBJ, "", "",
2632  {
2633  {RPCResult::Type::STR, "flag_name", "The name of the flag that was modified"},
2634  {RPCResult::Type::BOOL, "flag_state", "The new state of the flag"},
2635  {RPCResult::Type::STR, "warnings", "Any warnings associated with the change"},
2636  }
2637  },
2638  RPCExamples{
2639  HelpExampleCli("setwalletflag", "avoid_reuse")
2640  + HelpExampleRpc("setwalletflag", "\"avoid_reuse\"")
2641  },
2642  }.Check(request);
2643 
2644  std::string flag_str = request.params[0].get_str();
2645  bool value = request.params[1].isNull() || request.params[1].get_bool();
2646 
2647  if (!WALLET_FLAG_MAP.count(flag_str)) {
2648  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Unknown wallet flag: %s", flag_str));
2649  }
2650 
2651  auto flag = WALLET_FLAG_MAP.at(flag_str);
2652 
2653  if (!(flag & MUTABLE_WALLET_FLAGS)) {
2654  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Wallet flag is immutable: %s", flag_str));
2655  }
2656 
2657  UniValue res(UniValue::VOBJ);
2658 
2659  if (pwallet->IsWalletFlagSet(flag) == value) {
2660  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Wallet flag is already set to %s: %s", value ? "true" : "false", flag_str));
2661  }
2662 
2663  res.pushKV("flag_name", flag_str);
2664  res.pushKV("flag_state", value);
2665 
2666  if (value) {
2667  pwallet->SetWalletFlag(flag);
2668  } else {
2669  pwallet->UnsetWalletFlag(flag);
2670  }
2671 
2672  if (flag && value && WALLET_FLAG_CAVEATS.count(flag)) {
2673  res.pushKV("warnings", WALLET_FLAG_CAVEATS.at(flag));
2674  }
2675 
2676  return res;
2677 }
2678 
2679 static UniValue createwallet(const JSONRPCRequest& request)
2680 {
2681  RPCHelpMan{
2682  "createwallet",
2683  "\nCreates and loads a new wallet.\n",
2684  {
2685  {"wallet_name", RPCArg::Type::STR, RPCArg::Optional::NO, "The name for the new wallet. If this is a path, the wallet will be created at the path location."},
2686  {"disable_private_keys", RPCArg::Type::BOOL, /* default */ "false", "Disable the possibility of private keys (only watchonlys are possible in this mode)."},
2687  {"blank", RPCArg::Type::BOOL, /* default */ "false", "Create a blank wallet. A blank wallet has no keys or HD seed. One can be set using sethdseed."},
2688  {"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Encrypt the wallet with this passphrase."},
2689  {"avoid_reuse", RPCArg::Type::BOOL, /* default */ "false", "Keep track of coin reuse, and treat dirty and clean coins differently with privacy considerations in mind."},
2690  {"descriptors", RPCArg::Type::BOOL, /* default */ "false", "Create a native descriptor wallet. The wallet will use descriptors internally to handle address creation"},
2691  },
2692  RPCResult{
2693  RPCResult::Type::OBJ, "", "",
2694  {
2695  {RPCResult::Type::STR, "name", "The wallet name if created successfully. If the wallet was created using a full path, the wallet_name will be the full path."},
2696  {RPCResult::Type::STR, "warning", "Warning message if wallet was not loaded cleanly."},
2697  }
2698  },
2699  RPCExamples{
2700  HelpExampleCli("createwallet", "\"testwallet\"")
2701  + HelpExampleRpc("createwallet", "\"testwallet\"")
2702  },
2703  }.Check(request);
2704 
2705  uint64_t flags = 0;
2706  if (!request.params[1].isNull() && request.params[1].get_bool()) {
2708  }
2709 
2710  if (!request.params[2].isNull() && request.params[2].get_bool()) {
2711  flags |= WALLET_FLAG_BLANK_WALLET;
2712  }
2713  SecureString passphrase;
2714  passphrase.reserve(100);
2715  std::vector<bilingual_str> warnings;
2716  if (!request.params[3].isNull()) {
2717  passphrase = request.params[3].get_str().c_str();
2718  if (passphrase.empty()) {
2719  // Empty string means unencrypted
2720  warnings.emplace_back(Untranslated("Empty string given as passphrase, wallet will not be encrypted."));
2721  }
2722  }
2723 
2724  if (!request.params[4].isNull() && request.params[4].get_bool()) {
2725  flags |= WALLET_FLAG_AVOID_REUSE;
2726  }
2727  if (!request.params[5].isNull() && request.params[5].get_bool()) {
2728  flags |= WALLET_FLAG_DESCRIPTORS;
2729  warnings.emplace_back(Untranslated("Wallet is an experimental descriptor wallet"));
2730  }
2731 
2733  std::shared_ptr<CWallet> wallet;
2734  WalletCreationStatus status = CreateWallet(*g_rpc_chain, passphrase, flags, request.params[0].get_str(), error, warnings, wallet);
2735  switch (status) {
2737  throw JSONRPCError(RPC_WALLET_ERROR, error.original);
2741  break;
2742  // no default case, so the compiler can warn about missing cases
2743  }
2744 
2745  UniValue obj(UniValue::VOBJ);
2746  obj.pushKV("name", wallet->GetName());
2747  obj.pushKV("warning", Join(warnings, Untranslated("\n")).original);
2748 
2749  return obj;
2750 }
2751 
2752 static UniValue unloadwallet(const JSONRPCRequest& request)
2753 {
2754  RPCHelpMan{"unloadwallet",
2755  "Unloads the wallet referenced by the request endpoint otherwise unloads the wallet specified in the argument.\n"
2756  "Specifying the wallet name on a wallet endpoint is invalid.",
2757  {
2758  {"wallet_name", RPCArg::Type::STR, /* default */ "the wallet name from the RPC request", "The name of the wallet to unload."},
2759  },
2761  RPCExamples{
2762  HelpExampleCli("unloadwallet", "wallet_name")
2763  + HelpExampleRpc("unloadwallet", "wallet_name")
2764  },
2765  }.Check(request);
2766 
2767  std::string wallet_name;
2768  if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
2769  if (!request.params[0].isNull()) {
2770  throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot unload the requested wallet");
2771  }
2772  } else {
2773  wallet_name = request.params[0].get_str();
2774  }
2775 
2776  std::shared_ptr<CWallet> wallet = GetWallet(wallet_name);
2777  if (!wallet) {
2778  throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
2779  }
2780 
2781  // Release the "main" shared pointer and prevent further notifications.
2782  // Note that any attempt to load the same wallet would fail until the wallet
2783  // is destroyed (see CheckUniqueFileid).
2784  if (!RemoveWallet(wallet)) {
2785  throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
2786  }
2787 
2788  UnloadWallet(std::move(wallet));
2789 
2790  return NullUniValue;
2791 }
2792 
2793 static UniValue listunspent(const JSONRPCRequest& request)
2794 {
2795  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
2796  const CWallet* const pwallet = wallet.get();
2797 
2798  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2799  return NullUniValue;
2800  }
2801 
2802  RPCHelpMan{
2803  "listunspent",
2804  "\nReturns array of unspent transaction outputs\n"
2805  "with between minconf and maxconf (inclusive) confirmations.\n"
2806  "Optionally filter to only include txouts paid to specified addresses.\n",
2807  {
2808  {"minconf", RPCArg::Type::NUM, /* default */ "1", "The minimum confirmations to filter"},
2809  {"maxconf", RPCArg::Type::NUM, /* default */ "9999999", "The maximum confirmations to filter"},
2810  {"addresses", RPCArg::Type::ARR, /* default */ "empty array", "The bitcoin addresses to filter",
2811  {
2812  {"address", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "bitcoin address"},
2813  },
2814  },
2815  {"include_unsafe", RPCArg::Type::BOOL, /* default */ "true", "Include outputs that are not safe to spend\n"
2816  " See description of \"safe\" attribute below."},
2817  {"query_options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "JSON with query options",
2818  {
2819  {"minimumAmount", RPCArg::Type::AMOUNT, /* default */ "0", "Minimum value of each UTXO in " + CURRENCY_UNIT + ""},
2820  {"maximumAmount", RPCArg::Type::AMOUNT, /* default */ "unlimited", "Maximum value of each UTXO in " + CURRENCY_UNIT + ""},
2821  {"maximumCount", RPCArg::Type::NUM, /* default */ "unlimited", "Maximum number of UTXOs"},
2822  {"minimumSumAmount", RPCArg::Type::AMOUNT, /* default */ "unlimited", "Minimum sum value of all UTXOs in " + CURRENCY_UNIT + ""},
2823  },
2824  "query_options"},
2825  },
2826  RPCResult{
2827  RPCResult::Type::ARR, "", "",
2828  {
2829  {RPCResult::Type::OBJ, "", "",
2830  {
2831  {RPCResult::Type::STR_HEX, "txid", "the transaction id"},
2832  {RPCResult::Type::NUM, "vout", "the vout value"},
2833  {RPCResult::Type::STR, "address", "the bitcoin address"},
2834  {RPCResult::Type::STR, "label", "The associated label, or \"\" for the default label"},
2835  {RPCResult::Type::STR, "scriptPubKey", "the script key"},
2836  {RPCResult::Type::STR_AMOUNT, "amount", "the transaction output amount in " + CURRENCY_UNIT},
2837  {RPCResult::Type::NUM, "confirmations", "The number of confirmations"},
2838  {RPCResult::Type::STR_HEX, "redeemScript", "The redeemScript if scriptPubKey is P2SH"},
2839  {RPCResult::Type::STR, "witnessScript", "witnessScript if the scriptPubKey is P2WSH or P2SH-P2WSH"},
2840  {RPCResult::Type::BOOL, "spendable", "Whether we have the private keys to spend this output"},
2841  {RPCResult::Type::BOOL, "solvable", "Whether we know how to spend this output, ignoring the lack of keys"},
2842  {RPCResult::Type::BOOL, "reused", "(only present if avoid_reuse is set) Whether this output is reused/dirty (sent to an address that was previously spent from)"},
2843  {RPCResult::Type::STR, "desc", "(only when solvable) A descriptor for spending this output"},
2844  {RPCResult::Type::BOOL, "safe", "Whether this output is considered safe to spend. Unconfirmed transactions\n"
2845  "from outside keys and unconfirmed replacement transactions are considered unsafe\n"
2846  "and are not eligible for spending by fundrawtransaction and sendtoaddress."},
2847  }},
2848  }
2849  },
2850  RPCExamples{
2851  HelpExampleCli("listunspent", "")
2852  + HelpExampleCli("listunspent", "6 9999999 \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"")
2853  + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"")
2854  + HelpExampleCli("listunspent", "6 9999999 '[]' true '{ \"minimumAmount\": 0.005 }'")
2855  + HelpExampleRpc("listunspent", "6, 9999999, [] , true, { \"minimumAmount\": 0.005 } ")
2856  },
2857  }.Check(request);
2858 
2859  int nMinDepth = 1;
2860  if (!request.params[0].isNull()) {
2862  nMinDepth = request.params[0].get_int();
2863  }
2864 
2865  int nMaxDepth = 9999999;
2866  if (!request.params[1].isNull()) {
2868  nMaxDepth = request.params[1].get_int();
2869  }
2870 
2871  std::set<CTxDestination> destinations;
2872  if (!request.params[2].isNull()) {
2874  UniValue inputs = request.params[2].get_array();
2875  for (unsigned int idx = 0; idx < inputs.size(); idx++) {
2876  const UniValue& input = inputs[idx];
2877  CTxDestination dest = DecodeDestination(input.get_str());
2878  if (!IsValidDestination(dest)) {
2879  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + input.get_str());
2880  }
2881  if (!destinations.insert(dest).second) {
2882  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + input.get_str());
2883  }
2884  }
2885  }
2886 
2887  bool include_unsafe = true;
2888  if (!request.params[3].isNull()) {
2890  include_unsafe = request.params[3].get_bool();
2891  }
2892 
2893  CAmount nMinimumAmount = 0;
2894  CAmount nMaximumAmount = MAX_MONEY;
2895  CAmount nMinimumSumAmount = MAX_MONEY;
2896  uint64_t nMaximumCount = 0;
2897 
2898  if (!request.params[4].isNull()) {
2899  const UniValue& options = request.params[4].get_obj();
2900 
2901  if (options.exists("minimumAmount"))
2902  nMinimumAmount = AmountFromValue(options["minimumAmount"]);
2903 
2904  if (options.exists("maximumAmount"))
2905  nMaximumAmount = AmountFromValue(options["maximumAmount"]);
2906 
2907  if (options.exists("minimumSumAmount"))
2908  nMinimumSumAmount = AmountFromValue(options["minimumSumAmount"]);
2909 
2910  if (options.exists("maximumCount"))
2911  nMaximumCount = options["maximumCount"].get_int64();
2912  }
2913 
2914  // Make sure the results are valid at least up to the most recent block
2915  // the user could have gotten from another RPC command prior to now
2916  pwallet->BlockUntilSyncedToCurrentChain();
2917 
2918  UniValue results(UniValue::VARR);
2919  std::vector<COutput> vecOutputs;
2920  {
2921  CCoinControl cctl;
2922  cctl.m_avoid_address_reuse = false;
2923  cctl.m_min_depth = nMinDepth;
2924  cctl.m_max_depth = nMaxDepth;
2925  LOCK(pwallet->cs_wallet);
2926  pwallet->AvailableCoins(vecOutputs, !include_unsafe, &cctl, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount);
2927  }
2928 
2929  LOCK(pwallet->cs_wallet);
2930 
2931  const bool avoid_reuse = pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE);
2932 
2933  for (const COutput& out : vecOutputs) {
2934  CTxDestination address;
2935  const CScript& scriptPubKey = out.tx->tx->vout[out.i].scriptPubKey;
2936  bool fValidAddress = ExtractDestination(scriptPubKey, address);
2937  bool reused = avoid_reuse && pwallet->IsSpentKey(out.tx->GetHash(), out.i);
2938 
2939  if (destinations.size() && (!fValidAddress || !destinations.count(address)))
2940  continue;
2941 
2942  UniValue entry(UniValue::VOBJ);
2943  entry.pushKV("txid", out.tx->GetHash().GetHex());
2944  entry.pushKV("vout", out.i);
2945 
2946  if (fValidAddress) {
2947  entry.pushKV("address", EncodeDestination(address));
2948 
2949  const auto* address_book_entry = pwallet->FindAddressBookEntry(address);
2950  if (address_book_entry) {
2951  entry.pushKV("label", address_book_entry->GetLabel());
2952  }
2953 
2954  std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);
2955  if (provider) {
2956  if (scriptPubKey.IsPayToScriptHash()) {
2957  const CScriptID& hash = CScriptID(boost::get<ScriptHash>(address));
2958  CScript redeemScript;
2959  if (provider->GetCScript(hash, redeemScript)) {
2960  entry.pushKV("redeemScript", HexStr(redeemScript.begin(), redeemScript.end()));
2961  // Now check if the redeemScript is actually a P2WSH script
2962  CTxDestination witness_destination;
2963  if (redeemScript.IsPayToWitnessScriptHash()) {
2964  bool extracted = ExtractDestination(redeemScript, witness_destination);
2965  CHECK_NONFATAL(extracted);
2966  // Also return the witness script
2967  const WitnessV0ScriptHash& whash = boost::get<WitnessV0ScriptHash>(witness_destination);
2968  CScriptID id;
2969  CRIPEMD160().Write(whash.begin(), whash.size()).Finalize(id.begin());
2970  CScript witnessScript;
2971  if (provider->GetCScript(id, witnessScript)) {
2972  entry.pushKV("witnessScript", HexStr(witnessScript.begin(), witnessScript.end()));
2973  }
2974  }
2975  }
2976  } else if (scriptPubKey.IsPayToWitnessScriptHash()) {
2977  const WitnessV0ScriptHash& whash = boost::get<WitnessV0ScriptHash>(address);
2978  CScriptID id;
2979  CRIPEMD160().Write(whash.begin(), whash.size()).Finalize(id.begin());
2980  CScript witnessScript;
2981  if (provider->GetCScript(id, witnessScript)) {
2982  entry.pushKV("witnessScript", HexStr(witnessScript.begin(), witnessScript.end()));
2983  }
2984  }
2985  }
2986  }
2987 
2988  entry.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()));
2989  entry.pushKV("amount", ValueFromAmount(out.tx->tx->vout[out.i].nValue));
2990  entry.pushKV("confirmations", out.nDepth);
2991  entry.pushKV("spendable", out.fSpendable);
2992  entry.pushKV("solvable", out.fSolvable);
2993  if (out.fSolvable) {
2994  std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);
2995  if (provider) {
2996  auto descriptor = InferDescriptor(scriptPubKey, *provider);
2997  entry.pushKV("desc", descriptor->ToString());
2998  }
2999  }
3000  if (avoid_reuse) entry.pushKV("reused", reused);
3001  entry.pushKV("safe", out.fSafe);
3002  results.push_back(entry);
3003  }
3004 
3005  return results;
3006 }
3007 
3008 void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& fee_out, int& change_position, UniValue options)
3009 {
3010  // Make sure the results are valid at least up to the most recent block
3011  // the user could have gotten from another RPC command prior to now
3012  pwallet->BlockUntilSyncedToCurrentChain();
3013 
3014  CCoinControl coinControl;
3015  change_position = -1;
3016  bool lockUnspents = false;
3017  UniValue subtractFeeFromOutputs;
3018  std::set<int> setSubtractFeeFromOutputs;
3019 
3020  if (!options.isNull()) {
3021  if (options.type() == UniValue::VBOOL) {
3022  // backward compatibility bool only fallback
3023  coinControl.fAllowWatchOnly = options.get_bool();
3024  }
3025  else {
3027  RPCTypeCheckObj(options,
3028  {
3029  {"changeAddress", UniValueType(UniValue::VSTR)},
3030  {"changePosition", UniValueType(UniValue::VNUM)},
3031  {"change_type", UniValueType(UniValue::VSTR)},
3032  {"includeWatching", UniValueType(UniValue::VBOOL)},
3033  {"lockUnspents", UniValueType(UniValue::VBOOL)},
3034  {"feeRate", UniValueType()}, // will be checked below
3035  {"subtractFeeFromOutputs", UniValueType(UniValue::VARR)},
3036  {"replaceable", UniValueType(UniValue::VBOOL)},
3037  {"conf_target", UniValueType(UniValue::VNUM)},
3038  {"estimate_mode", UniValueType(UniValue::VSTR)},
3039  },
3040  true, true);
3041 
3042  if (options.exists("changeAddress")) {
3043  CTxDestination dest = DecodeDestination(options["changeAddress"].get_str());
3044 
3045  if (!IsValidDestination(dest)) {
3046  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "changeAddress must be a valid bitcoin address");
3047  }
3048 
3049  coinControl.destChange = dest;
3050  }
3051 
3052  if (options.exists("changePosition"))
3053  change_position = options["changePosition"].get_int();
3054 
3055  if (options.exists("change_type")) {
3056  if (options.exists("changeAddress")) {
3057  throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both changeAddress and address_type options");
3058  }
3059  coinControl.m_change_type = pwallet->m_default_change_type;
3060  if (!ParseOutputType(options["change_type"].get_str(), *coinControl.m_change_type)) {
3061  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown change type '%s'", options["change_type"].get_str()));
3062  }
3063  }
3064 
3065  coinControl.fAllowWatchOnly = ParseIncludeWatchonly(options["includeWatching"], *pwallet);
3066 
3067  if (options.exists("lockUnspents"))
3068  lockUnspents = options["lockUnspents"].get_bool();
3069 
3070  if (options.exists("feeRate"))
3071  {
3072  coinControl.m_feerate = CFeeRate(AmountFromValue(options["feeRate"]));
3073  coinControl.fOverrideFeeRate = true;
3074  }
3075 
3076  if (options.exists("subtractFeeFromOutputs"))
3077  subtractFeeFromOutputs = options["subtractFeeFromOutputs"].get_array();
3078 
3079  if (options.exists("replaceable")) {
3080  coinControl.m_signal_bip125_rbf = options["replaceable"].get_bool();
3081  }
3082  if (options.exists("conf_target")) {
3083  if (options.exists("feeRate")) {
3084  throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both conf_target and feeRate");
3085  }
3086  coinControl.m_confirm_target = ParseConfirmTarget(options["conf_target"], pwallet->chain().estimateMaxBlocks());
3087  }
3088  if (options.exists("estimate_mode")) {
3089  if (options.exists("feeRate")) {
3090  throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both estimate_mode and feeRate");
3091  }
3092  if (!FeeModeFromString(options["estimate_mode"].get_str(), coinControl.m_fee_mode)) {
3093  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter");
3094  }
3095  }
3096  }
3097  } else {
3098  // if options is null and not a bool
3099  coinControl.fAllowWatchOnly = ParseIncludeWatchonly(NullUniValue, *pwallet);
3100  }
3101 
3102  if (tx.vout.size() == 0)
3103  throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output");
3104 
3105  if (change_position != -1 && (change_position < 0 || (unsigned int)change_position > tx.vout.size()))
3106  throw JSONRPCError(RPC_INVALID_PARAMETER, "changePosition out of bounds");
3107 
3108  for (unsigned int idx = 0; idx < subtractFeeFromOutputs.size(); idx++) {
3109  int pos = subtractFeeFromOutputs[idx].get_int();
3110  if (setSubtractFeeFromOutputs.count(pos))
3111  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, duplicated position: %d", pos));
3112  if (pos < 0)
3113  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, negative position: %d", pos));
3114  if (pos >= int(tx.vout.size()))
3115  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, position too large: %d", pos));
3116  setSubtractFeeFromOutputs.insert(pos);
3117  }
3118 
3120 
3121  if (!pwallet->FundTransaction(tx, fee_out, change_position, error, lockUnspents, setSubtractFeeFromOutputs, coinControl)) {
3122  throw JSONRPCError(RPC_WALLET_ERROR, error.original);
3123  }
3124 }
3125 
3127 {
3128  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
3129  CWallet* const pwallet = wallet.get();
3130 
3131  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
3132  return NullUniValue;
3133  }
3134 
3135  RPCHelpMan{"fundrawtransaction",
3136  "\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
3137  "This will not modify existing inputs, and will add at most one change output to the outputs.\n"
3138  "No existing outputs will be modified unless \"subtractFeeFromOutputs\" is specified.\n"
3139  "Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n"
3140  "The inputs added will not be signed, use signrawtransactionwithkey\n"
3141  " or signrawtransactionwithwallet for that.\n"
3142  "Note that all existing inputs must have their previous output transaction be in the wallet.\n"
3143  "Note that all inputs selected must be of standard form and P2SH scripts must be\n"
3144  "in the wallet using importaddress or addmultisigaddress (to calculate fees).\n"
3145  "You can see whether this is the case by checking the \"solvable\" field in the listunspent output.\n"
3146  "Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n",
3147  {
3148  {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex string of the raw transaction"},
3149  {"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}",
3150  {
3151  {"changeAddress", RPCArg::Type::STR, /* default */ "pool address", "The bitcoin address to receive the change"},
3152  {"changePosition", RPCArg::Type::NUM, /* default */ "random", "The index of the change output"},
3153  {"change_type", RPCArg::Type::STR, /* default */ "set by -changetype", "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
3154  {"includeWatching", RPCArg::Type::BOOL, /* default */ "true for watch-only wallets, otherwise false", "Also select inputs which are watch only.\n"
3155  "Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n"
3156  "e.g. with 'importpubkey' or 'importmulti' with the 'pubkeys' or 'desc' field."},
3157  {"lockUnspents", RPCArg::Type::BOOL, /* default */ "false", "Lock selected unspent outputs"},
3158  {"feeRate", RPCArg::Type::AMOUNT, /* default */ "not set: makes wallet determine the fee", "Set a specific fee rate in " + CURRENCY_UNIT + "/kB"},
3159  {"subtractFeeFromOutputs", RPCArg::Type::ARR, /* default */ "empty array", "The integers.\n"
3160  " The fee will be equally deducted from the amount of each specified output.\n"
3161  " Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
3162  " If no outputs are specified here, the sender pays the fee.",
3163  {
3164  {"vout_index", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "The zero-based output index, before a change output is added."},
3165  },
3166  },
3167  {"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Marks this transaction as BIP125 replaceable.\n"
3168  " Allows this transaction to be replaced by a transaction with higher fees"},
3169  {"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks)"},
3170  {"estimate_mode", RPCArg::Type::STR, /* default */ "UNSET", "The fee estimate mode, must be one of:\n"
3171  " \"UNSET\"\n"
3172  " \"ECONOMICAL\"\n"
3173  " \"CONSERVATIVE\""},
3174  },
3175  "options"},
3176  {"iswitness", RPCArg::Type::BOOL, /* default */ "depends on heuristic tests", "Whether the transaction hex is a serialized witness transaction.\n"
3177  "If iswitness is not present, heuristic tests will be used in decoding.\n"
3178  "If true, only witness deserialization will be tried.\n"
3179  "If false, only non-witness deserialization will be tried.\n"
3180  "This boolean should reflect whether the transaction has inputs\n"
3181  "(e.g. fully valid, or on-chain transactions), if known by the caller."
3182  },
3183  },
3184  RPCResult{
3185  RPCResult::Type::OBJ, "", "",
3186  {
3187  {RPCResult::Type::STR_HEX, "hex", "The resulting raw transaction (hex-encoded string)"},
3188  {RPCResult::Type::STR_AMOUNT, "fee", "Fee in " + CURRENCY_UNIT + " the resulting transaction pays"},
3189  {RPCResult::Type::NUM, "changepos", "The position of the added change output, or -1"},
3190  }
3191  },
3192  RPCExamples{
3193  "\nCreate a transaction with no inputs\n"
3194  + HelpExampleCli("createrawtransaction", "\"[]\" \"{\\\"myaddress\\\":0.01}\"") +
3195  "\nAdd sufficient unsigned inputs to meet the output value\n"
3196  + HelpExampleCli("fundrawtransaction", "\"rawtransactionhex\"") +
3197  "\nSign the transaction\n"
3198  + HelpExampleCli("signrawtransactionwithwallet", "\"fundedtransactionhex\"") +
3199  "\nSend the transaction\n"
3200  + HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
3201  },
3202  }.Check(request);
3203 
3204  RPCTypeCheck(request.params, {UniValue::VSTR, UniValueType(), UniValue::VBOOL});
3205 
3206  // parse hex string from parameter
3208  bool try_witness = request.params[2].isNull() ? true : request.params[2].get_bool();
3209  bool try_no_witness = request.params[2].isNull() ? true : !request.params[2].get_bool();
3210  if (!DecodeHexTx(tx, request.params[0].get_str(), try_no_witness, try_witness)) {
3211  throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
3212  }
3213 
3214  CAmount fee;
3215  int change_position;
3216  FundTransaction(pwallet, tx, fee, change_position, request.params[1]);
3217 
3218  UniValue result(UniValue::VOBJ);
3219  result.pushKV("hex", EncodeHexTx(CTransaction(tx)));
3220  result.pushKV("fee", ValueFromAmount(fee));
3221  result.pushKV("changepos", change_position);
3222 
3223  return result;
3224 }
3225 
3227 {
3228  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
3229  const CWallet* const pwallet = wallet.get();
3230 
3231  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
3232  return NullUniValue;
3233  }
3234 
3235  RPCHelpMan{"signrawtransactionwithwallet",
3236  "\nSign inputs for raw transaction (serialized, hex-encoded).\n"
3237  "The second optional argument (may be null) is an array of previous transaction outputs that\n"
3238  "this transaction depends on but may not yet be in the block chain." +
3240  {
3241  {"hexstring", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction hex string"},
3242  {"prevtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "The previous dependent transaction outputs",
3243  {
3245  {
3246  {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
3247  {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
3248  {"scriptPubKey", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "script key"},
3249  {"redeemScript", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "(required for P2SH) redeem script"},
3250  {"witnessScript", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "(required for P2WSH or P2SH-P2WSH) witness script"},
3251  {"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::OMITTED, "(required for Segwit inputs) the amount spent"},
3252  },
3253  },
3254  },
3255  },
3256  {"sighashtype", RPCArg::Type::STR, /* default */ "ALL", "The signature hash type. Must be one of\n"
3257  " \"ALL\"\n"
3258  " \"NONE\"\n"
3259  " \"SINGLE\"\n"
3260  " \"ALL|ANYONECANPAY\"\n"
3261  " \"NONE|ANYONECANPAY\"\n"
3262  " \"SINGLE|ANYONECANPAY\""},
3263  },
3264  RPCResult{
3265  RPCResult::Type::OBJ, "", "",
3266  {
3267  {RPCResult::Type::STR_HEX, "hex", "The hex-encoded raw transaction with signature(s)"},
3268  {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},
3269  {RPCResult::Type::ARR, "errors", "Script verification errors (if there are any)",
3270  {
3271  {RPCResult::Type::OBJ, "", "",
3272  {
3273  {RPCResult::Type::STR_HEX, "txid", "The hash of the referenced, previous transaction"},
3274  {RPCResult::Type::NUM, "vout", "The index of the output to spent and used as input"},
3275  {RPCResult::Type::STR_HEX, "scriptSig", "The hex-encoded signature script"},
3276  {RPCResult::Type::NUM, "sequence", "Script sequence number"},
3277  {RPCResult::Type::STR, "error", "Verification or signing error related to the input"},
3278  }},
3279  }},
3280  }
3281  },
3282  RPCExamples{
3283  HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"")
3284  + HelpExampleRpc("signrawtransactionwithwallet", "\"myhex\"")
3285  },
3286  }.Check(request);
3287 
3288  RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VSTR}, true);
3289 
3290  CMutableTransaction mtx;
3291  if (!DecodeHexTx(mtx, request.params[0].get_str(), true)) {
3292  throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
3293  }
3294 
3295  // Sign the transaction
3296  LOCK(pwallet->cs_wallet);
3297  EnsureWalletIsUnlocked(pwallet);
3298 
3299  // Fetch previous transactions (inputs):
3300  std::map<COutPoint, Coin> coins;
3301  for (const CTxIn& txin : mtx.vin) {
3302  coins[txin.prevout]; // Create empty map entry keyed by prevout.
3303  }
3304  pwallet->chain().findCoins(coins);
3305 
3306  // Parse the prevtxs array
3307  ParsePrevouts(request.params[1], nullptr, coins);
3308 
3309  int nHashType = ParseSighashString(request.params[2]);
3310 
3311  // Script verification errors
3312  std::map<int, std::string> input_errors;
3313 
3314  bool complete = pwallet->SignTransaction(mtx, coins, nHashType, input_errors);
3315  UniValue result(UniValue::VOBJ);
3316  SignTransactionResultToJSON(mtx, complete, coins, input_errors, result);
3317  return result;
3318 }
3319 
3320 static UniValue bumpfee(const JSONRPCRequest& request)
3321 {
3322  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
3323  CWallet* const pwallet = wallet.get();
3324 
3325 
3326  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
3327  return NullUniValue;
3328 
3329  RPCHelpMan{"bumpfee",
3330  "\nBumps the fee of an opt-in-RBF transaction T, replacing it with a new transaction B.\n"
3331  "An opt-in RBF transaction with the given txid must be in the wallet.\n"
3332  "The command will pay the additional fee by reducing change outputs or adding inputs when necessary. It may add a new change output if one does not already exist.\n"
3333  "All inputs in the original transaction will be included in the replacement transaction.\n"
3334  "The command will fail if the wallet or mempool contains a transaction that spends one of T's outputs.\n"
3335  "By default, the new fee will be calculated automatically using estimatesmartfee.\n"
3336  "The user can specify a confirmation target for estimatesmartfee.\n"
3337  "Alternatively, the user can specify a fee_rate (" + CURRENCY_UNIT + " per kB) for the new transaction.\n"
3338  "At a minimum, the new fee rate must be high enough to pay an additional new relay fee (incrementalfee\n"
3339  "returned by getnetworkinfo) to enter the node's mempool.\n",
3340  {
3341  {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The txid to be bumped"},
3343  {
3344  {"confTarget", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks)"},
3345  {"fee_rate", RPCArg::Type::NUM, /* default */ "fall back to 'confTarget'", "fee rate (NOT total fee) to pay, in " + CURRENCY_UNIT + " per kB\n"
3346  " Specify a fee rate instead of relying on the built-in fee estimator.\n"
3347  "Must be at least 0.0001 " + CURRENCY_UNIT + " per kB higher than the current transaction fee rate.\n"},
3348  {"replaceable", RPCArg::Type::BOOL, /* default */ "true", "Whether the new transaction should still be\n"
3349  " marked bip-125 replaceable. If true, the sequence numbers in the transaction will\n"
3350  " be left unchanged from the original. If false, any input sequence numbers in the\n"
3351  " original transaction that were less than 0xfffffffe will be increased to 0xfffffffe\n"
3352  " so the new transaction will not be explicitly bip-125 replaceable (though it may\n"
3353  " still be replaceable in practice, for example if it has unconfirmed ancestors which\n"
3354  " are replaceable)."},
3355  {"estimate_mode", RPCArg::Type::STR, /* default */ "UNSET", "The fee estimate mode, must be one of:\n"
3356  " \"UNSET\"\n"
3357  " \"ECONOMICAL\"\n"
3358  " \"CONSERVATIVE\""},
3359  },
3360  "options"},
3361  },
3362  RPCResult{
3363  RPCResult::Type::OBJ, "", "", {
3364  {RPCResult::Type::STR, "psbt", "The base64-encoded unsigned PSBT of the new transaction. Only returned when wallet private keys are disabled."},
3365  {RPCResult::Type::STR_HEX, "txid", "The id of the new transaction. Only returned when wallet private keys are enabled."},
3366  {RPCResult::Type::STR_AMOUNT, "origfee", "The fee of the replaced transaction."},
3367  {RPCResult::Type::STR_AMOUNT, "fee", "The fee of the new transaction."},
3368  {RPCResult::Type::ARR, "errors", "Errors encountered during processing (may be empty).",
3369  {
3370  {RPCResult::Type::STR, "", ""},
3371  }},
3372  }
3373  },
3374  RPCExamples{
3375  "\nBump the fee, get the new transaction\'s txid\n" +
3376  HelpExampleCli("bumpfee", "<txid>")
3377  },
3378  }.Check(request);
3379 
3380  RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ});
3381  uint256 hash(ParseHashV(request.params[0], "txid"));
3382 
3383  CCoinControl coin_control;
3385  // optional parameters
3386  coin_control.m_signal_bip125_rbf = true;
3387 
3388  if (!request.params[1].isNull()) {
3389  UniValue options = request.params[1];
3390  RPCTypeCheckObj(options,
3391  {
3392  {"confTarget", UniValueType(UniValue::VNUM)},
3393  {"fee_rate", UniValueType(UniValue::VNUM)},
3394  {"replaceable", UniValueType(UniValue::VBOOL)},
3395  {"estimate_mode", UniValueType(UniValue::VSTR)},
3396  },
3397  true, true);
3398  if (options.exists("confTarget") && options.exists("fee_rate")) {
3399  throw JSONRPCError(RPC_INVALID_PARAMETER, "confTarget can't be set with fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate.");
3400  } else if (options.exists("confTarget")) { // TODO: alias this to conf_target
3401  coin_control.m_confirm_target = ParseConfirmTarget(options["confTarget"], pwallet->chain().estimateMaxBlocks());
3402  } else if (options.exists("fee_rate")) {
3403  CFeeRate fee_rate(AmountFromValue(options["fee_rate"]));
3404  if (fee_rate <= CFeeRate(0)) {
3405  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid fee_rate %s (must be greater than 0)", fee_rate.ToString()));
3406  }
3407  coin_control.m_feerate = fee_rate;
3408  }
3409 
3410  if (options.exists("replaceable")) {
3411  coin_control.m_signal_bip125_rbf = options["replaceable"].get_bool();
3412  }
3413  if (options.exists("estimate_mode")) {
3414  if (!FeeModeFromString(options["estimate_mode"].get_str(), coin_control.m_fee_mode)) {
3415  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter");
3416  }
3417  }
3418  }
3419 
3420  // Make sure the results are valid at least up to the most recent block
3421  // the user could have gotten from another RPC command prior to now
3422  pwallet->BlockUntilSyncedToCurrentChain();
3423 
3424  LOCK(pwallet->cs_wallet);
3425  EnsureWalletIsUnlocked(pwallet);
3426 
3427 
3428  std::vector<bilingual_str> errors;
3429  CAmount old_fee;
3430  CAmount new_fee;
3431  CMutableTransaction mtx;
3432  feebumper::Result res;
3433  // Targeting feerate bump.
3434  res = feebumper::CreateRateBumpTransaction(*pwallet, hash, coin_control, errors, old_fee, new_fee, mtx);
3435  if (res != feebumper::Result::OK) {
3436  switch(res) {
3438  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, errors[0].original);
3439  break;
3441  throw JSONRPCError(RPC_INVALID_REQUEST, errors[0].original);
3442  break;
3444  throw JSONRPCError(RPC_INVALID_PARAMETER, errors[0].original);
3445  break;
3447  throw JSONRPCError(RPC_WALLET_ERROR, errors[0].original);
3448  break;
3449  default:
3450  throw JSONRPCError(RPC_MISC_ERROR, errors[0].original);
3451  break;
3452  }
3453  }
3454 
3455  UniValue result(UniValue::VOBJ);
3456 
3457  // If wallet private keys are enabled, return the new transaction id,
3458  // otherwise return the base64-encoded unsigned PSBT of the new transaction.
3460  if (!feebumper::SignTransaction(*pwallet, mtx)) {
3461  throw JSONRPCError(RPC_WALLET_ERROR, "Can't sign transaction.");
3462  }
3463 
3464  uint256 txid;
3465  if (feebumper::CommitTransaction(*pwallet, hash, std::move(mtx), errors, txid) != feebumper::Result::OK) {
3466  throw JSONRPCError(RPC_WALLET_ERROR, errors[0].original);
3467  }
3468 
3469  result.pushKV("txid", txid.GetHex());
3470  } else {
3471  PartiallySignedTransaction psbtx(mtx);
3472  bool complete = false;
3473  const TransactionError err = pwallet->FillPSBT(psbtx, complete, SIGHASH_ALL, false /* sign */, true /* bip32derivs */);
3475  CHECK_NONFATAL(!complete);
3477  ssTx << psbtx;
3478  result.pushKV("psbt", EncodeBase64(ssTx.str()));
3479  }
3480 
3481  result.pushKV("origfee", ValueFromAmount(old_fee));
3482  result.pushKV("fee", ValueFromAmount(new_fee));
3483  UniValue result_errors(UniValue::VARR);
3484  for (const bilingual_str& error : errors) {
3485  result_errors.push_back(error.original);
3486  }
3487  result.pushKV("errors", result_errors);
3488 
3489  return result;
3490 }
3491 
3493 {
3494  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
3495  CWallet* const pwallet = wallet.get();
3496 
3497  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
3498  return NullUniValue;
3499  }
3500 
3501  RPCHelpMan{"rescanblockchain",
3502  "\nRescan the local blockchain for wallet related transactions.\n"
3503  "Note: Use \"getwalletinfo\" to query the scanning progress.\n",
3504  {
3505  {"start_height", RPCArg::Type::NUM, /* default */ "0", "block height where the rescan should start"},
3506  {"stop_height", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "the last block height that should be scanned. If none is provided it will rescan up to the tip at return time of this call."},
3507  },
3508  RPCResult{
3509  RPCResult::Type::OBJ, "", "",
3510  {
3511  {RPCResult::Type::NUM, "start_height", "The block height where the rescan started (the requested height or 0)"},
3512  {RPCResult::Type::NUM, "stop_height", "The height of the last rescanned block. May be null in rare cases if there was a reorg and the call didn't scan any blocks because they were already scanned in the background."},
3513  }
3514  },
3515  RPCExamples{
3516  HelpExampleCli("rescanblockchain", "100000 120000")
3517  + HelpExampleRpc("rescanblockchain", "100000, 120000")
3518  },
3519  }.Check(request);
3520 
3521  WalletRescanReserver reserver(*pwallet);
3522  if (!reserver.reserve()) {
3523  throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
3524  }
3525 
3526  int start_height = 0;
3527  Optional<int> stop_height;
3528  uint256 start_block;
3529  {
3530  LOCK(pwallet->cs_wallet);
3531  int tip_height = pwallet->GetLastBlockHeight();
3532 
3533  if (!request.params[0].isNull()) {
3534  start_height = request.params[0].get_int();
3535  if (start_height < 0 || start_height > tip_height) {
3536  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid start_height");
3537  }
3538  }
3539 
3540  if (!request.params[1].isNull()) {
3541  stop_height = request.params[1].get_int();
3542  if (*stop_height < 0 || *stop_height > tip_height) {
3543  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid stop_height");
3544  } else if (*stop_height < start_height) {
3545  throw JSONRPCError(RPC_INVALID_PARAMETER, "stop_height must be greater than start_height");
3546  }
3547  }
3548 
3549  // We can't rescan beyond non-pruned blocks, stop and throw an error
3550  if (!pwallet->chain().hasBlocks(pwallet->GetLastBlockHash(), start_height, stop_height)) {
3551  throw JSONRPCError(RPC_MISC_ERROR, "Can't rescan beyond pruned data. Use RPC call getblockchaininfo to determine your pruned height.");
3552  }
3553 
3554  CHECK_NONFATAL(pwallet->chain().findAncestorByHeight(pwallet->GetLastBlockHash(), start_height, FoundBlock().hash(start_block)));
3555  }
3556 
3557  CWallet::ScanResult result =
3558  pwallet->ScanForWalletTransactions(start_block, start_height, stop_height, reserver, true /* fUpdate */);
3559  switch (result.status) {
3561  break;
3563  throw JSONRPCError(RPC_MISC_ERROR, "Rescan failed. Potentially corrupted data files.");
3565  throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted.");
3566  // no default case, so the compiler can warn about missing cases
3567  }
3568  UniValue response(UniValue::VOBJ);
3569  response.pushKV("start_height", start_height);
3570  response.pushKV("stop_height", result.last_scanned_height ? *result.last_scanned_height : UniValue());
3571  return response;
3572 }
3573 
3574 class DescribeWalletAddressVisitor : public boost::static_visitor<UniValue>
3575 {
3576 public:
3577  const SigningProvider * const provider;
3578 
3579  void ProcessSubScript(const CScript& subscript, UniValue& obj) const
3580  {
3581  // Always present: script type and redeemscript
3582  std::vector<std::vector<unsigned char>> solutions_data;
3583  txnouttype which_type = Solver(subscript, solutions_data);
3584  obj.pushKV("script", GetTxnOutputType(which_type));
3585  obj.pushKV("hex", HexStr(subscript.begin(), subscript.end()));
3586 
3587  CTxDestination embedded;
3588  if (ExtractDestination(subscript, embedded)) {
3589  // Only when the script corresponds to an address.
3590  UniValue subobj(UniValue::VOBJ);
3591  UniValue detail = DescribeAddress(embedded);
3592  subobj.pushKVs(detail);
3593  UniValue wallet_detail = boost::apply_visitor(*this, embedded);
3594  subobj.pushKVs(wallet_detail);
3595  subobj.pushKV("address", EncodeDestination(embedded));
3596  subobj.pushKV("scriptPubKey", HexStr(subscript.begin(), subscript.end()));
3597  // Always report the pubkey at the top level, so that `getnewaddress()['pubkey']` always works.
3598  if (subobj.exists("pubkey")) obj.pushKV("pubkey", subobj["pubkey"]);
3599  obj.pushKV("embedded", std::move(subobj));
3600  } else if (which_type == TX_MULTISIG) {
3601  // Also report some information on multisig scripts (which do not have a corresponding address).
3602  // TODO: abstract out the common functionality between this logic and ExtractDestinations.
3603  obj.pushKV("sigsrequired", solutions_data[0][0]);
3604  UniValue pubkeys(UniValue::VARR);
3605  for (size_t i = 1; i < solutions_data.size() - 1; ++i) {
3606  CPubKey key(solutions_data[i].begin(), solutions_data[i].end());
3607  pubkeys.push_back(HexStr(key.begin(), key.end()));
3608  }
3609  obj.pushKV("pubkeys", std::move(pubkeys));
3610  }
3611  }
3612 
3613  explicit DescribeWalletAddressVisitor(const SigningProvider* _provider) : provider(_provider) {}
3614 
3616 
3617  UniValue operator()(const PKHash& pkhash) const
3618  {
3619  CKeyID keyID(pkhash);
3620  UniValue obj(UniValue::VOBJ);
3621  CPubKey vchPubKey;
3622  if (provider && provider->GetPubKey(keyID, vchPubKey)) {
3623  obj.pushKV("pubkey", HexStr(vchPubKey));
3624  obj.pushKV("iscompressed", vchPubKey.IsCompressed());
3625  }
3626  return obj;
3627  }
3628 
3629  UniValue operator()(const ScriptHash& scripthash) const
3630  {
3631  CScriptID scriptID(scripthash);
3632  UniValue obj(UniValue::VOBJ);
3633  CScript subscript;
3634  if (provider && provider->GetCScript(scriptID, subscript)) {
3635  ProcessSubScript(subscript, obj);
3636  }
3637  return obj;
3638  }
3639 
3641  {
3642  UniValue obj(UniValue::VOBJ);
3643  CPubKey pubkey;
3644  if (provider && provider->GetPubKey(CKeyID(id), pubkey)) {
3645  obj.pushKV("pubkey", HexStr(pubkey));
3646  }
3647  return obj;
3648  }
3649 
3651  {
3652  UniValue obj(UniValue::VOBJ);
3653  CScript subscript;
3654  CRIPEMD160 hasher;
3655  uint160 hash;
3656  hasher.Write(id.begin(), 32).Finalize(hash.begin());
3657  if (provider && provider->GetCScript(CScriptID(hash), subscript)) {
3658  ProcessSubScript(subscript, obj);
3659  }
3660  return obj;
3661  }
3662 
3664 };
3665 
3666 static UniValue DescribeWalletAddress(const CWallet* const pwallet, const CTxDestination& dest)
3667 {
3668  UniValue ret(UniValue::VOBJ);
3669  UniValue detail = DescribeAddress(dest);
3670  CScript script = GetScriptForDestination(dest);
3671  std::unique_ptr<SigningProvider> provider = nullptr;
3672  if (pwallet) {
3673  provider = pwallet->GetSolvingProvider(script);
3674  }
3675  ret.pushKVs(detail);
3676  ret.pushKVs(boost::apply_visitor(DescribeWalletAddressVisitor(provider.get()), dest));
3677  return ret;
3678 }
3679 
3681 static UniValue AddressBookDataToJSON(const CAddressBookData& data, const bool verbose)
3682 {
3683  UniValue ret(UniValue::VOBJ);
3684  if (verbose) {
3685  ret.pushKV("name", data.GetLabel());
3686  }
3687  ret.pushKV("purpose", data.purpose);
3688  return ret;
3689 }
3690 
3692 {
3693  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
3694  const CWallet* const pwallet = wallet.get();
3695 
3696  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
3697  return NullUniValue;
3698  }
3699 
3700  RPCHelpMan{"getaddressinfo",
3701  "\nReturn information about the given bitcoin address.\n"
3702  "Some of the information will only be present if the address is in the active wallet.\n",
3703  {
3704  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address for which to get information."},
3705  },
3706  RPCResult{
3707  RPCResult::Type::OBJ, "", "",
3708  {
3709  {RPCResult::Type::STR, "address", "The bitcoin address validated."},
3710  {RPCResult::Type::STR_HEX, "scriptPubKey", "The hex-encoded scriptPubKey generated by the address."},
3711  {RPCResult::Type::BOOL, "ismine", "If the address is yours."},
3712  {RPCResult::Type::BOOL, "iswatchonly", "If the address is watchonly."},
3713  {RPCResult::Type::BOOL, "solvable", "If we know how to spend coins sent to this address, ignoring the possible lack of private keys."},
3714  {RPCResult::Type::STR, "desc", /* optional */ true, "A descriptor for spending coins sent to this address (only when solvable)."},
3715  {RPCResult::Type::BOOL, "isscript", "If the key is a script."},
3716  {RPCResult::Type::BOOL, "ischange", "If the address was used for change output."},
3717  {RPCResult::Type::BOOL, "iswitness", "If the address is a witness address."},
3718  {RPCResult::Type::NUM, "witness_version", /* optional */ true, "The version number of the witness program."},
3719  {RPCResult::Type::STR_HEX, "witness_program", /* optional */ true, "The hex value of the witness program."},
3720  {RPCResult::Type::STR, "script", /* optional */ true, "The output script type. Only if isscript is true and the redeemscript is known. Possible\n"
3721  " types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_keyhash,\n"
3722  "witness_v0_scripthash, witness_unknown."},
3723  {RPCResult::Type::STR_HEX, "hex", /* optional */ true, "The redeemscript for the p2sh address."},
3724  {RPCResult::Type::ARR, "pubkeys", /* optional */ true, "Array of pubkeys associated with the known redeemscript (only if script is multisig).",
3725  {
3726  {RPCResult::Type::STR, "pubkey", ""},
3727  }},
3728  {RPCResult::Type::NUM, "sigsrequired", /* optional */ true, "The number of signatures required to spend multisig output (only if script is multisig)."},
3729  {RPCResult::Type::STR_HEX, "pubkey", /* optional */ true, "The hex value of the raw public key for single-key addresses (possibly embedded in P2SH or P2WSH)."},
3730  {RPCResult::Type::OBJ, "embedded", /* optional */ true, "Information about the address embedded in P2SH or P2WSH, if relevant and known.",
3731  {
3732  {RPCResult::Type::ELISION, "", "Includes all\n"
3733  " getaddressinfo output fields for the embedded address, excluding metadata (timestamp, hdkeypath,\n"
3734  "hdseedid) and relation to the wallet (ismine, iswatchonly)."},
3735  }},
3736  {RPCResult::Type::BOOL, "iscompressed", /* optional */ true, "If the pubkey is compressed."},
3737  {RPCResult::Type::STR, "label", "DEPRECATED. The label associated with the address. Defaults to \"\". Replaced by the labels array below."},
3738  {RPCResult::Type::NUM_TIME, "timestamp", /* optional */ true, "The creation time of the key, if available, expressed in " + UNIX_EPOCH_TIME + "."},
3739  {RPCResult::Type::STR, "hdkeypath", /* optional */ true, "The HD keypath, if the key is HD and available."},
3740  {RPCResult::Type::STR_HEX, "hdseedid", /* optional */ true, "The Hash160 of the HD seed."},
3741  {RPCResult::Type::STR_HEX, "hdmasterfingerprint", /* optional */ true, "The fingerprint of the master key."},
3742  {RPCResult::Type::ARR, "labels", "Array of labels associated with the address. Currently limited to one label but returned\n"
3743  "as an array to keep the API stable if multiple labels are enabled in the future.",
3744  {
3745  {RPCResult::Type::STR, "label name", "The label name. Defaults to \"\"."},
3746  {RPCResult::Type::OBJ, "", "label data, DEPRECATED, will be removed in 0.21. To re-enable, launch bitcoind with `-deprecatedrpc=labelspurpose`",
3747  {
3748  {RPCResult::Type::STR, "name", "The label name. Defaults to \"\"."},
3749  {RPCResult::Type::STR, "purpose", "The purpose of the associated address (send or receive)."},
3750  }},
3751  }},
3752  }
3753  },
3754  RPCExamples{
3755  HelpExampleCli("getaddressinfo", "\"" + EXAMPLE_ADDRESS[0] + "\"") +
3756  HelpExampleRpc("getaddressinfo", "\"" + EXAMPLE_ADDRESS[0] + "\"")
3757  },
3758  }.Check(request);
3759 
3760  LOCK(pwallet->cs_wallet);
3761 
3762  UniValue ret(UniValue::VOBJ);
3763  CTxDestination dest = DecodeDestination(request.params[0].get_str());
3764  // Make sure the destination is valid
3765  if (!IsValidDestination(dest)) {
3766  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
3767  }
3768 
3769  std::string currentAddress = EncodeDestination(dest);
3770  ret.pushKV("address", currentAddress);
3771 
3772  CScript scriptPubKey = GetScriptForDestination(dest);
3773  ret.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()));
3774 
3775  std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);
3776 
3777  isminetype mine = pwallet->IsMine(dest);
3778  ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE));
3779 
3780  bool solvable = provider && IsSolvable(*provider, scriptPubKey);
3781  ret.pushKV("solvable", solvable);
3782 
3783  if (solvable) {
3784  ret.pushKV("desc", InferDescriptor(scriptPubKey, *provider)->ToString());
3785  }
3786 
3787  ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY));
3788 
3789  UniValue detail = DescribeWalletAddress(pwallet, dest);
3790  ret.pushKVs(detail);
3791 
3792  // DEPRECATED: Return label field if existing. Currently only one label can
3793  // be associated with an address, so the label should be equivalent to the
3794  // value of the name key/value pair in the labels array below.
3795  const auto* address_book_entry = pwallet->FindAddressBookEntry(dest);
3796  if (pwallet->chain().rpcEnableDeprecated("label") && address_book_entry) {
3797  ret.pushKV("label", address_book_entry->GetLabel());
3798  }
3799 
3800  ret.pushKV("ischange", pwallet->IsChange(scriptPubKey));
3801 
3802  ScriptPubKeyMan* spk_man = pwallet->GetScriptPubKeyMan(scriptPubKey);
3803  if (spk_man) {
3804  if (const std::unique_ptr<CKeyMetadata> meta = spk_man->GetMetadata(dest)) {
3805  ret.pushKV("timestamp", meta->nCreateTime);
3806  if (meta->has_key_origin) {
3807  ret.pushKV("hdkeypath", WriteHDKeypath(meta->key_origin.path));
3808  ret.pushKV("hdseedid", meta->hd_seed_id.GetHex());
3809  ret.pushKV("hdmasterfingerprint", HexStr(meta->key_origin.fingerprint, meta->key_origin.fingerprint + 4));
3810  }
3811  }
3812  }
3813 
3814  // Return a `labels` array containing the label associated with the address,
3815  // equivalent to the `label` field above. Currently only one label can be
3816  // associated with an address, but we return an array so the API remains
3817  // stable if we allow multiple labels to be associated with an address in
3818  // the future.
3819  UniValue labels(UniValue::VARR);
3820  if (address_book_entry) {
3821  // DEPRECATED: The previous behavior of returning an array containing a
3822  // JSON object of `name` and `purpose` key/value pairs is deprecated.
3823  if (pwallet->chain().rpcEnableDeprecated("labelspurpose")) {
3824  labels.push_back(AddressBookDataToJSON(*address_book_entry, true));
3825  } else {
3826  labels.push_back(address_book_entry->GetLabel());
3827  }
3828  }
3829  ret.pushKV("labels", std::move(labels));
3830 
3831  return ret;
3832 }
3833 
3835 {
3836  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
3837  const CWallet* const pwallet = wallet.get();
3838 
3839  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
3840  return NullUniValue;
3841  }
3842 
3843  RPCHelpMan{"getaddressesbylabel",
3844  "\nReturns the list of addresses assigned the specified label.\n",
3845  {
3846  {"label", RPCArg::Type::STR, RPCArg::Optional::NO, "The label."},
3847  },
3848  RPCResult{
3849  RPCResult::Type::OBJ_DYN, "", "json object with addresses as keys",
3850  {
3851  {RPCResult::Type::OBJ, "address", "json object with information about address",
3852  {
3853  {RPCResult::Type::STR, "purpose", "Purpose of address (\"send\" for sending address, \"receive\" for receiving address)"},
3854  }},
3855  }
3856  },
3857  RPCExamples{
3858  HelpExampleCli("getaddressesbylabel", "\"tabby\"")
3859  + HelpExampleRpc("getaddressesbylabel", "\"tabby\"")
3860  },
3861  }.Check(request);
3862 
3863  LOCK(pwallet->cs_wallet);
3864 
3865  std::string label = LabelFromValue(request.params[0]);
3866 
3867  // Find all addresses that have the given label
3868  UniValue ret(UniValue::VOBJ);
3869  std::set<std::string> addresses;
3870  for (const std::pair<const CTxDestination, CAddressBookData>& item : pwallet->m_address_book) {
3871  if (item.second.IsChange()) continue;
3872  if (item.second.GetLabel() == label) {
3873  std::string address = EncodeDestination(item.first);
3874  // CWallet::m_address_book is not expected to contain duplicate
3875  // address strings, but build a separate set as a precaution just in
3876  // case it does.
3877  bool unique = addresses.emplace(address).second;
3878  CHECK_NONFATAL(unique);
3879  // UniValue::pushKV checks if the key exists in O(N)
3880  // and since duplicate addresses are unexpected (checked with
3881  // std::set in O(log(N))), UniValue::__pushKV is used instead,
3882  // which currently is O(1).
3883  ret.__pushKV(address, AddressBookDataToJSON(item.second, false));
3884  }
3885  }
3886 
3887  if (ret.empty()) {
3888  throw JSONRPCError(RPC_WALLET_INVALID_LABEL_NAME, std::string("No addresses with label " + label));
3889  }
3890 
3891  return ret;
3892 }
3893 
3894 static UniValue listlabels(const JSONRPCRequest& request)
3895 {
3896  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
3897  const CWallet* const pwallet = wallet.get();
3898 
3899  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
3900  return NullUniValue;
3901  }
3902 
3903  RPCHelpMan{"listlabels",
3904  "\nReturns the list of all labels, or labels that are assigned to addresses with a specific purpose.\n",
3905  {
3906  {"purpose", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "Address purpose to list labels for ('send','receive'). An empty string is the same as not providing this argument."},
3907  },
3908  RPCResult{
3909  RPCResult::Type::ARR, "", "",
3910  {
3911  {RPCResult::Type::STR, "label", "Label name"},
3912  }
3913  },
3914  RPCExamples{
3915  "\nList all labels\n"
3916  + HelpExampleCli("listlabels", "") +
3917  "\nList labels that have receiving addresses\n"
3918  + HelpExampleCli("listlabels", "receive") +
3919  "\nList labels that have sending addresses\n"
3920  + HelpExampleCli("listlabels", "send") +
3921  "\nAs a JSON-RPC call\n"
3922  + HelpExampleRpc("listlabels", "receive")
3923  },
3924  }.Check(request);
3925 
3926  LOCK(pwallet->cs_wallet);
3927 
3928  std::string purpose;
3929  if (!request.params[0].isNull()) {
3930  purpose = request.params[0].get_str();
3931  }
3932 
3933  // Add to a set to sort by label name, then insert into Univalue array
3934  std::set<std::string> label_set;
3935  for (const std::pair<const CTxDestination, CAddressBookData>& entry : pwallet->m_address_book) {
3936  if (entry.second.IsChange()) continue;
3937  if (purpose.empty() || entry.second.purpose == purpose) {
3938  label_set.insert(entry.second.GetLabel());
3939  }
3940  }
3941 
3942  UniValue ret(UniValue::VARR);
3943  for (const std::string& name : label_set) {
3944  ret.push_back(name);
3945  }
3946 
3947  return ret;
3948 }
3949 
3951 {
3952  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
3953  CWallet* const pwallet = wallet.get();
3954 
3955  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
3956  return NullUniValue;
3957  }
3958 
3959  RPCHelpMan{"sethdseed",
3960  "\nSet or generate a new HD wallet seed. Non-HD wallets will not be upgraded to being a HD wallet. Wallets that are already\n"
3961  "HD will have a new HD seed set so that new keys added to the keypool will be derived from this new seed.\n"
3962  "\nNote that you will need to MAKE A NEW BACKUP of your wallet after setting the HD wallet seed." +
3964  {
3965  {"newkeypool", RPCArg::Type::BOOL, /* default */ "true", "Whether to flush old unused addresses, including change addresses, from the keypool and regenerate it.\n"
3966  " If true, the next address from getnewaddress and change address from getrawchangeaddress will be from this new seed.\n"
3967  " If false, addresses (including change addresses if the wallet already had HD Chain Split enabled) from the existing\n"
3968  " keypool will be used until it has been depleted."},
3969  {"seed", RPCArg::Type::STR, /* default */ "random seed", "The WIF private key to use as the new HD seed.\n"
3970  " The seed value can be retrieved using the dumpwallet command. It is the private key marked hdseed=1"},
3971  },
3973  RPCExamples{
3974  HelpExampleCli("sethdseed", "")
3975  + HelpExampleCli("sethdseed", "false")
3976  + HelpExampleCli("sethdseed", "true \"wifkey\"")
3977  + HelpExampleRpc("sethdseed", "true, \"wifkey\"")
3978  },
3979  }.Check(request);
3980 
3981  LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet, true);
3982 
3984  throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set a HD seed to a wallet with private keys disabled");
3985  }
3986 
3987  LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore);
3988 
3989  // Do not do anything to non-HD wallets
3990  if (!pwallet->CanSupportFeature(FEATURE_HD)) {
3991  throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set a HD seed on a non-HD wallet. Use the upgradewallet RPC in order to upgrade a non-HD wallet to HD");
3992  }
3993 
3994  EnsureWalletIsUnlocked(pwallet);
3995 
3996  bool flush_key_pool = true;
3997  if (!request.params[0].isNull()) {
3998  flush_key_pool = request.params[0].get_bool();
3999  }
4000 
4001  CPubKey master_pub_key;
4002  if (request.params[1].isNull()) {
4003  master_pub_key = spk_man.GenerateNewSeed();
4004  } else {
4005  CKey key = DecodeSecret(request.params[1].get_str());
4006  if (!key.IsValid()) {
4007  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
4008  }
4009 
4010  if (HaveKey(spk_man, key)) {
4011  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key (either as an HD seed or as a loose private key)");
4012  }
4013 
4014  master_pub_key = spk_man.DeriveNewSeed(key);
4015  }
4016 
4017  spk_man.SetHDSeed(master_pub_key);
4018  if (flush_key_pool) spk_man.NewKeyPool();
4019 
4020  return NullUniValue;
4021 }
4022 
4024 {
4025  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
4026  const CWallet* const pwallet = wallet.get();
4027 
4028  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
4029  return NullUniValue;
4030  }
4031 
4032  RPCHelpMan{"walletprocesspsbt",
4033  "\nUpdate a PSBT with input information from our wallet and then sign inputs\n"
4034  "that we can sign for." +
4036  {
4037  {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction base64 string"},
4038  {"sign", RPCArg::Type::BOOL, /* default */ "true", "Also sign the transaction when updating"},
4039  {"sighashtype", RPCArg::Type::STR, /* default */ "ALL", "The signature hash type to sign with if not specified by the PSBT. Must be one of\n"
4040  " \"ALL\"\n"
4041  " \"NONE\"\n"
4042  " \"SINGLE\"\n"
4043  " \"ALL|ANYONECANPAY\"\n"
4044  " \"NONE|ANYONECANPAY\"\n"
4045  " \"SINGLE|ANYONECANPAY\""},
4046  {"bip32derivs", RPCArg::Type::BOOL, /* default */ "true", "Include BIP 32 derivation paths for public keys if we know them"},
4047  },
4048  RPCResult{
4049  RPCResult::Type::OBJ, "", "",
4050  {
4051  {RPCResult::Type::STR, "psbt", "The base64-encoded partially signed transaction"},
4052  {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},
4053  }
4054  },
4055  RPCExamples{
4056  HelpExampleCli("walletprocesspsbt", "\"psbt\"")
4057  },
4058  }.Check(request);
4059 
4060  RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL, UniValue::VSTR});
4061 
4062  // Unserialize the transaction
4064  std::string error;
4065  if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
4066  throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
4067  }
4068 
4069  // Get the sighash type
4070  int nHashType = ParseSighashString(request.params[2]);
4071 
4072  // Fill transaction with our data and also sign
4073  bool sign = request.params[1].isNull() ? true : request.params[1].get_bool();
4074  bool bip32derivs = request.params[3].isNull() ? true : request.params[3].get_bool();
4075  bool complete = true;
4076  const TransactionError err = pwallet->FillPSBT(psbtx, complete, nHashType, sign, bip32derivs);
4077  if (err != TransactionError::OK) {
4078  throw JSONRPCTransactionError(err);
4079  }
4080 
4081  UniValue result(UniValue::VOBJ);
4083  ssTx << psbtx;
4084  result.pushKV("psbt", EncodeBase64(ssTx.str()));
4085  result.pushKV("complete", complete);
4086 
4087  return result;
4088 }
4089 
4091 {
4092  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
4093  CWallet* const pwallet = wallet.get();
4094 
4095  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
4096  return NullUniValue;
4097  }
4098 
4099  RPCHelpMan{"walletcreatefundedpsbt",
4100  "\nCreates and funds a transaction in the Partially Signed Transaction format. Inputs will be added if supplied inputs are not enough\n"
4101  "Implements the Creator and Updater roles.\n",
4102  {
4103  {"inputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The inputs",
4104  {
4106  {
4107  {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
4108  {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
4109  {"sequence", RPCArg::Type::NUM, RPCArg::Optional::NO, "The sequence number"},
4110  },
4111  },
4112  },
4113  },
4114  {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The outputs (key-value pairs), where none of the keys are duplicated.\n"
4115  "That is, each address can only appear once and there can only be one 'data' object.\n"
4116  "For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n"
4117  " accepted as second parameter.",
4118  {
4120  {
4121  {"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "A key-value pair. The key (string) is the bitcoin address, the value (float or string) is the amount in " + CURRENCY_UNIT + ""},
4122  },
4123  },
4125  {
4126  {"data", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "A key-value pair. The key must be \"data\", the value is hex-encoded data"},
4127  },
4128  },
4129  },
4130  },
4131  {"locktime", RPCArg::Type::NUM, /* default */ "0", "Raw locktime. Non-0 value also locktime-activates inputs"},
4133  {
4134  {"changeAddress", RPCArg::Type::STR_HEX, /* default */ "pool address", "The bitcoin address to receive the change"},
4135  {"changePosition", RPCArg::Type::NUM, /* default */ "random", "The index of the change output"},
4136  {"change_type", RPCArg::Type::STR, /* default */ "set by -changetype", "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
4137  {"includeWatching", RPCArg::Type::BOOL, /* default */ "true for watch-only wallets, otherwise false", "Also select inputs which are watch only"},
4138  {"lockUnspents", RPCArg::Type::BOOL, /* default */ "false", "Lock selected unspent outputs"},
4139  {"feeRate", RPCArg::Type::AMOUNT, /* default */ "not set: makes wallet determine the fee", "Set a specific fee rate in " + CURRENCY_UNIT + "/kB"},
4140  {"subtractFeeFromOutputs", RPCArg::Type::ARR, /* default */ "empty array", "The outputs to subtract the fee from.\n"
4141  " The fee will be equally deducted from the amount of each specified output.\n"
4142  " Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
4143  " If no outputs are specified here, the sender pays the fee.",
4144  {
4145  {"vout_index", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "The zero-based output index, before a change output is added."},
4146  },
4147  },
4148  {"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Marks this transaction as BIP125 replaceable.\n"
4149  " Allows this transaction to be replaced by a transaction with higher fees"},
4150  {"conf_target", RPCArg::Type::NUM, /* default */ "fall back to wallet's confirmation target (txconfirmtarget)", "Confirmation target (in blocks)"},
4151  {"estimate_mode", RPCArg::Type::STR, /* default */ "UNSET", "The fee estimate mode, must be one of:\n"
4152  " \"UNSET\"\n"
4153  " \"ECONOMICAL\"\n"
4154  " \"CONSERVATIVE\""},
4155  },
4156  "options"},
4157  {"bip32derivs", RPCArg::Type::BOOL, /* default */ "true", "Include BIP 32 derivation paths for public keys if we know them"},
4158  },
4159  RPCResult{
4160  RPCResult::Type::OBJ, "", "",
4161  {
4162  {RPCResult::Type::STR, "psbt", "The resulting raw transaction (base64-encoded string)"},
4163  {RPCResult::Type::STR_AMOUNT, "fee", "Fee in " + CURRENCY_UNIT + " the resulting transaction pays"},
4164  {RPCResult::Type::NUM, "changepos", "The position of the added change output, or -1"},
4165  }
4166  },
4167  RPCExamples{
4168  "\nCreate a transaction with no inputs\n"
4169  + HelpExampleCli("walletcreatefundedpsbt", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"")
4170  },
4171  }.Check(request);
4172 
4173  RPCTypeCheck(request.params, {
4174  UniValue::VARR,
4175  UniValueType(), // ARR or OBJ, checked later
4176  UniValue::VNUM,
4177  UniValue::VOBJ,
4178  UniValue::VBOOL
4179  }, true
4180  );
4181 
4182  CAmount fee;
4183  int change_position;
4184  bool rbf = pwallet->m_signal_rbf;
4185  const UniValue &replaceable_arg = request.params[3]["replaceable"];
4186  if (!replaceable_arg.isNull()) {
4187  RPCTypeCheckArgument(replaceable_arg, UniValue::VBOOL);
4188  rbf = replaceable_arg.isTrue();
4189  }
4190  CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], rbf);
4191  FundTransaction(pwallet, rawTx, fee, change_position, request.params[3]);
4192 
4193  // Make a blank psbt
4194  PartiallySignedTransaction psbtx(rawTx);
4195 
4196  // Fill transaction with out data but don't sign
4197  bool bip32derivs = request.params[4].isNull() ? true : request.params[4].get_bool();
4198  bool complete = true;
4199  const TransactionError err = pwallet->FillPSBT(psbtx, complete, 1, false, bip32derivs);
4200  if (err != TransactionError::OK) {
4201  throw JSONRPCTransactionError(err);
4202  }
4203 
4204  // Serialize the PSBT
4206  ssTx << psbtx;
4207 
4208  UniValue result(UniValue::VOBJ);
4209  result.pushKV("psbt", EncodeBase64(ssTx.str()));
4210  result.pushKV("fee", ValueFromAmount(fee));
4211  result.pushKV("changepos", change_position);
4212  return result;
4213 }
4214 
4215 static UniValue upgradewallet(const JSONRPCRequest& request)
4216 {
4217  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
4218  CWallet* const pwallet = wallet.get();
4219 
4220  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
4221  return NullUniValue;
4222  }
4223 
4224  RPCHelpMan{"upgradewallet",
4225  "\nUpgrade the wallet. Upgrades to the latest version if no version number is specified\n"
4226  "New keys may be generated and a new wallet backup will need to be made.",
4227  {
4228  {"version", RPCArg::Type::NUM, /* default */ strprintf("%d", FEATURE_LATEST), "The version number to upgrade to. Default is the latest wallet version"}
4229  },
4230  RPCResults{},
4231  RPCExamples{
4232  HelpExampleCli("upgradewallet", "169900")
4233  + HelpExampleRpc("upgradewallet", "169900")
4234  }
4235  }.Check(request);
4236 
4237  RPCTypeCheck(request.params, {UniValue::VNUM}, true);
4238 
4239  EnsureWalletIsUnlocked(pwallet);
4240 
4241  int version = 0;
4242  if (!request.params[0].isNull()) {
4243  version = request.params[0].get_int();
4244  }
4245 
4247  std::vector<bilingual_str> warnings;
4248  if (!pwallet->UpgradeWallet(version, error, warnings)) {
4249  throw JSONRPCError(RPC_WALLET_ERROR, error.original);
4250  }
4251  return error.original;
4252 }
4253 
4254 UniValue abortrescan(const JSONRPCRequest& request); // in rpcdump.cpp
4255 UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp
4256 UniValue importprivkey(const JSONRPCRequest& request);
4257 UniValue importaddress(const JSONRPCRequest& request);
4258 UniValue importpubkey(const JSONRPCRequest& request);
4259 UniValue dumpwallet(const JSONRPCRequest& request);
4260 UniValue importwallet(const JSONRPCRequest& request);
4261 UniValue importprunedfunds(const JSONRPCRequest& request);
4262 UniValue removeprunedfunds(const JSONRPCRequest& request);
4263 UniValue importmulti(const JSONRPCRequest& request);
4264 UniValue importdescriptors(const JSONRPCRequest& request);
4265 
4266 void RegisterWalletRPCCommands(interfaces::Chain& chain, std::vector<std::unique_ptr<interfaces::Handler>>& handlers)
4267 {
4268 // clang-format off
4269 static const CRPCCommand commands[] =
4270 { // category name actor (function) argNames
4271  // --------------------- ------------------------ ----------------------- ----------
4272  { "rawtransactions", "fundrawtransaction", &fundrawtransaction, {"hexstring","options","iswitness"} },
4273  { "wallet", "abandontransaction", &abandontransaction, {"txid"} },
4274  { "wallet", "abortrescan", &abortrescan, {} },
4275  { "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","label","address_type"} },
4276  { "wallet", "backupwallet", &backupwallet, {"destination"} },
4277  { "wallet", "bumpfee", &bumpfee, {"txid", "options"} },
4278  { "wallet", "createwallet", &createwallet, {"wallet_name", "disable_private_keys", "blank", "passphrase", "avoid_reuse", "descriptors"} },
4279  { "wallet", "dumpprivkey", &dumpprivkey, {"address"} },
4280  { "wallet", "dumpwallet", &dumpwallet, {"filename"} },
4281  { "wallet", "encryptwallet", &encryptwallet, {"passphrase"} },
4282  { "wallet", "getaddressesbylabel", &getaddressesbylabel, {"label"} },
4283  { "wallet", "getaddressinfo", &getaddressinfo, {"address"} },
4284  { "wallet", "getbalance", &getbalance, {"dummy","minconf","include_watchonly","avoid_reuse"} },
4285  { "wallet", "getnewaddress", &getnewaddress, {"label","address_type"} },
4286  { "wallet", "getrawchangeaddress", &getrawchangeaddress, {"address_type"} },
4287  { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, {"address","minconf"} },
4288  { "wallet", "getreceivedbylabel", &getreceivedbylabel, {"label","minconf"} },
4289  { "wallet", "gettransaction", &gettransaction, {"txid","include_watchonly","verbose"} },
4290  { "wallet", "getunconfirmedbalance", &getunconfirmedbalance, {} },
4291  { "wallet", "getbalances", &getbalances, {} },
4292  { "wallet", "getwalletinfo", &getwalletinfo, {} },
4293  { "wallet", "importaddress", &importaddress, {"address","label","rescan","p2sh"} },
4294  { "wallet", "importdescriptors", &importdescriptors, {"requests"} },
4295  { "wallet", "importmulti", &importmulti, {"requests","options"} },
4296  { "wallet", "importprivkey", &importprivkey, {"privkey","label","rescan"} },
4297  { "wallet", "importprunedfunds", &importprunedfunds, {"rawtransaction","txoutproof"} },
4298  { "wallet", "importpubkey", &importpubkey, {"pubkey","label","rescan"} },
4299  { "wallet", "importwallet", &importwallet, {"filename"} },
4300  { "wallet", "keypoolrefill", &keypoolrefill, {"newsize"} },
4301  { "wallet", "listaddressgroupings", &listaddressgroupings, {} },
4302  { "wallet", "listlabels", &listlabels, {"purpose"} },
4303  { "wallet", "listlockunspent", &listlockunspent, {} },
4304  { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, {"minconf","include_empty","include_watchonly","address_filter"} },
4305  { "wallet", "listreceivedbylabel", &listreceivedbylabel, {"minconf","include_empty","include_watchonly"} },
4306  { "wallet", "listsinceblock", &listsinceblock, {"blockhash","target_confirmations","include_watchonly","include_removed"} },
4307  { "wallet", "listtransactions", &listtransactions, {"label|dummy","count","skip","include_watchonly"} },
4308  { "wallet", "listunspent", &listunspent, {"minconf","maxconf","addresses","include_unsafe","query_options"} },
4309  { "wallet", "listwalletdir", &listwalletdir, {} },
4310  { "wallet", "listwallets", &listwallets, {} },
4311  { "wallet", "loadwallet", &loadwallet, {"filename"} },
4312  { "wallet", "lockunspent", &lockunspent, {"unlock","transactions"} },
4313  { "wallet", "removeprunedfunds", &removeprunedfunds, {"txid"} },
4314  { "wallet", "rescanblockchain", &rescanblockchain, {"start_height", "stop_height"} },
4315  { "wallet", "sendmany", &sendmany, {"dummy","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode"} },
4316  { "wallet", "sendtoaddress", &sendtoaddress, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode","avoid_reuse"} },
4317  { "wallet", "sethdseed", &sethdseed, {"newkeypool","seed"} },
4318  { "wallet", "setlabel", &setlabel, {"address","label"} },
4319  { "wallet", "settxfee", &settxfee, {"amount"} },
4320  { "wallet", "setwalletflag", &setwalletflag, {"flag","value"} },
4321  { "wallet", "signmessage", &signmessage, {"address","message"} },
4322  { "wallet", "signrawtransactionwithwallet", &signrawtransactionwithwallet, {"hexstring","prevtxs","sighashtype"} },
4323  { "wallet", "unloadwallet", &unloadwallet, {"wallet_name"} },
4324  { "wallet", "upgradewallet", &upgradewallet, {"version"} },
4325  { "wallet", "walletcreatefundedpsbt", &walletcreatefundedpsbt, {"inputs","outputs","locktime","options","bip32derivs"} },
4326  { "wallet", "walletlock", &walletlock, {} },
4327  { "wallet", "walletpassphrase", &walletpassphrase, {"passphrase","timeout"} },
4328  { "wallet", "walletpassphrasechange", &walletpassphrasechange, {"oldpassphrase","newpassphrase"} },
4329  { "wallet", "walletprocesspsbt", &walletprocesspsbt, {"psbt","sign","sighashtype","bip32derivs"} },
4330 };
4331 // clang-format on
4332 
4333  for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
4334  handlers.emplace_back(chain.handleRpc(commands[vcidx]));
4335 }
4336 
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:387
No wallet specified (error when there are multiple wallets loaded)
Definition: protocol.h:80
CAmount nValue
Definition: transaction.h:123
CPubKey AddrToPubKey(const FillableSigningProvider &keystore, const std::string &addr_in)
Definition: util.cpp:140
Helper for findBlock to selectively return pieces of block data.
Definition: chain.h:35
bool NewKeyPool()
Mark old keypool keys as used, and generate all new keys.
bool IsWalletFlagSet(uint64_t flag) const override
check if a certain wallet flag is set
Definition: wallet.cpp:1383
virtual bool findCommonAncestor(const uint256 &block_hash1, const uint256 &block_hash2, const FoundBlock &ancestor_out={}, const FoundBlock &block1_out={}, const FoundBlock &block2_out={})=0
Find most recent common ancestor between two blocks and optionally return block information.
static UniValue DescribeWalletAddress(const CWallet *const pwallet, const CTxDestination &dest)
Definition: rpcwallet.cpp:3666
const std::map< uint64_t, std::string > WALLET_FLAG_CAVEATS
Definition: wallet.cpp:42
static UniValue signmessage(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:514
virtual void findCoins(std::map< COutPoint, Coin > &coins)=0
Look up unspent output information.
const CHDChain & GetHDChain() const
OutputType m_default_change_type
Definition: wallet.h:1015
void RPCTypeCheck(const UniValue &params, const std::list< UniValueType > &typesExpected, bool fAllowNull)
Type-check arguments; throws JSONRPCError if wrong type given.
Definition: util.cpp:22
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:3181
static UniValue lockunspent(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:2111
virtual int rpcSerializationFlags()=0
Current RPC serialization flags.
bool IsLegacy() const
Determine if we are a legacy wallet.
Definition: wallet.cpp:4390
UniValue operator()(const CNoDestination &dest) const
Definition: rpcwallet.cpp:3615
static UniValue addmultisigaddress(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:916
bool SignTransaction(CWallet &wallet, CMutableTransaction &mtx)
Sign the new transaction,.
Definition: feebumper.cpp:242
const std::vector< UniValue > & getValues() const
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:158
bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest &request, std::string &wallet_name)
Definition: rpcwallet.cpp:82
Keypool ran out, call keypoolrefill first.
Definition: protocol.h:73
UniValue importwallet(const JSONRPCRequest &request)
Definition: rpcdump.cpp:510
UniValue operator()(const ScriptHash &scripthash) const
Definition: rpcwallet.cpp:3629
static UniValue listreceivedbyaddress(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:1158
bool fAllowWatchOnly
Includes watch only addresses which are solvable.
Definition: coincontrol.h:32
std::map< std::string, std::string > mapValue_t
Definition: wallet.h:214
Enter the wallet passphrase with walletpassphrase first.
Definition: protocol.h:74
static UniValue getreceivedbylabel(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:659
std::vector< std::shared_ptr< CWallet > > GetWallets()
Definition: dummywallet.cpp:71
CScript scriptPubKey
Definition: transaction.h:124
static UniValue listunspent(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:2793
void UnloadWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly unload and delete the wallet.
Definition: wallet.cpp:129
void UnlockCoin(const COutPoint &output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:3455
std::shared_ptr< CWallet > LoadWallet(interfaces::Chain &chain, const std::string &name, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: dummywallet.cpp:76
std::shared_ptr< CWallet > GetWallet(const std::string &name)
Definition: wallet.cpp:91
bool get_bool() const
UniValue operator()(const WitnessV0ScriptHash &id) const
Definition: rpcwallet.cpp:3650
void ParsePrevouts(const UniValue &prevTxsUnival, FillableSigningProvider *keystore, std::map< COutPoint, Coin > &coins)
Parse a prevtxs UniValue array and get the map of coins from it.
static UniValue loadwallet(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:2565
Required arg.
static UniValue settxfee(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:2292
static UniValue unloadwallet(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:2752
Bilingual messages:
Definition: translation.h:16
Definition: block.h:62
Optional< T > MakeOptional(bool condition, T &&value)
Substitute for C++17 std::make_optional.
Definition: optional.h:18
static UniValue getunconfirmedbalance(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:756
auto Join(const std::vector< T > &list, const BaseType &separator, UnaryOp unary_op) -> decltype(unary_op(list.at(0)))
Join a list of items.
Definition: string.h:34
bool IsValidDestinationString(const std::string &str, const CChainParams &params)
Definition: key_io.cpp:220
static const CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
Definition: amount.h:25
const std::string & GetLabel() const
Definition: wallet.h:200
static UniValue getrawchangeaddress(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:239
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1164
virtual void rpcRunLater(const std::string &name, std::function< void()> fn, int64_t seconds)=0
Run function after given number of seconds. Cancel any previous calls with same name.
bool IsPayToScriptHash() const
Definition: script.cpp:198
RecursiveMutex cs_KeyStore
bool IsFromMe(const isminefilter &filter) const
Definition: wallet.h:489
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:184
CAmount m_mine_untrusted_pending
Untrusted, but in mempool (pending)
Definition: wallet.h:929
static UniValue AddressBookDataToJSON(const CAddressBookData &data, const bool verbose)
Convert CAddressBookData to JSON record.
Definition: rpcwallet.cpp:3681
std::vector< uint256 > txids
Definition: rpcwallet.cpp:1004
std::vector< CTxIn > vin
Definition: transaction.h:347
bool UpgradeWallet(int version, bilingual_str &error, std::vector< bilingual_str > &warnings)
Upgrade the wallet.
Definition: wallet.cpp:4022
SigningResult
Definition: message.h:42
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition: translation.h:35
LegacyScriptPubKeyMan & EnsureLegacyScriptPubKeyMan(CWallet &wallet, bool also_create)
Definition: rpcwallet.cpp:125
void AvailableCoins(std::vector< COutput > &vCoins, bool fOnlySafe=true, const CCoinControl *coinControl=nullptr, const CAmount &nMinimumAmount=1, const CAmount &nMaximumAmount=MAX_MONEY, const CAmount &nMinimumSumAmount=MAX_MONEY, const uint64_t nMaximumCount=0) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
populate vCoins with vector of available COutputs.
Definition: wallet.cpp:2067
TxItems wtxOrdered
Definition: wallet.h:784
std::string str() const
Definition: streams.h:279
UniValue getaddressinfo(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:3691
const std::string UNIX_EPOCH_TIME
String used to describe UNIX epoch time in documentation, factored out to a constant for consistency...
Definition: util.cpp:19
CAmount GetDebit(const isminefilter &filter) const
filter decides which addresses will count towards the debit
Definition: wallet.cpp:1815
CFeeRate m_pay_tx_fee
Definition: wallet.h:1001
int64_t GetOldestKeyPoolTime() const
Definition: wallet.cpp:3236
#define ARRAYLEN(array)
Utilities for converting data from/to strings.
Definition: strencodings.h:19
static bool ParseIncludeWatchonly(const UniValue &include_watchonly, const CWallet &pwallet)
Used by RPC commands that have an include_watchonly parameter.
Definition: rpcwallet.cpp:62
bool Lock()
Definition: wallet.cpp:4175
#define CHECK_NONFATAL(condition)
Throw a NonFatalCheckError when the condition evaluates to false.
Definition: check.h:32
void EnsureWalletIsUnlocked(const CWallet *pwallet)
Definition: rpcwallet.cpp:117
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:327
static UniValue walletlock(const JSONRPCRequest &request)
Definition: rpcwallet.cpp:2011