Bitcoin ABC  0.29.6
P2P Digital Currency
rpcwallet.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2019 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 <chainparams.h> // for GetConsensus.
7 #include <coins.h>
8 #include <common/system.h>
9 #include <config.h>
10 #include <consensus/amount.h>
11 #include <consensus/validation.h>
12 #include <core_io.h>
13 #include <interfaces/chain.h>
14 #include <key_io.h>
15 #include <node/context.h>
16 #include <outputtype.h>
17 #include <policy/fees.h>
18 #include <policy/policy.h>
20 #include <rpc/server.h>
21 #include <rpc/util.h>
22 #include <script/descriptor.h>
23 #include <util/bip32.h>
24 #include <util/error.h>
25 #include <util/moneystr.h>
26 #include <util/string.h>
27 #include <util/translation.h>
28 #include <util/url.h>
29 #include <util/vector.h>
30 #include <wallet/coincontrol.h>
31 #include <wallet/context.h>
32 #include <wallet/load.h>
33 #include <wallet/receive.h>
34 #include <wallet/rpc/util.h>
35 #include <wallet/rpcwallet.h>
36 #include <wallet/spend.h>
37 #include <wallet/wallet.h>
38 #include <wallet/walletdb.h>
39 #include <wallet/walletutil.h>
40 
41 #include <univalue.h>
42 
43 #include <event2/http.h>
44 
45 #include <optional>
46 #include <variant>
47 
49 
53 bool HaveKey(const SigningProvider &wallet, const CKey &key) {
54  CKey key2;
55  key2.Set(key.begin(), key.end(), !key.IsCompressed());
56  return wallet.HaveKey(key.GetPubKey().GetID()) ||
57  wallet.HaveKey(key2.GetPubKey().GetID());
58 }
59 
60 static void WalletTxToJSON(const CWallet &wallet, const CWalletTx &wtx,
61  UniValue &entry)
62  EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet) {
63  interfaces::Chain &chain = wallet.chain();
64  int confirms = wallet.GetTxDepthInMainChain(wtx);
65  entry.pushKV("confirmations", confirms);
66  if (wtx.IsCoinBase()) {
67  entry.pushKV("generated", true);
68  }
69  if (confirms > 0) {
70  entry.pushKV("blockhash", wtx.m_confirm.hashBlock.GetHex());
71  entry.pushKV("blockheight", wtx.m_confirm.block_height);
72  entry.pushKV("blockindex", wtx.m_confirm.nIndex);
73  int64_t block_time;
74  CHECK_NONFATAL(chain.findBlock(wtx.m_confirm.hashBlock,
75  FoundBlock().time(block_time)));
76  entry.pushKV("blocktime", block_time);
77  } else {
78  entry.pushKV("trusted", CachedTxIsTrusted(wallet, wtx));
79  }
80  uint256 hash = wtx.GetId();
81  entry.pushKV("txid", hash.GetHex());
82  UniValue conflicts(UniValue::VARR);
83  for (const uint256 &conflict : wallet.GetTxConflicts(wtx)) {
84  conflicts.push_back(conflict.GetHex());
85  }
86  entry.pushKV("walletconflicts", conflicts);
87  entry.pushKV("time", wtx.GetTxTime());
88  entry.pushKV("timereceived", int64_t{wtx.nTimeReceived});
89 
90  for (const std::pair<const std::string, std::string> &item : wtx.mapValue) {
91  entry.pushKV(item.first, item.second);
92  }
93 }
94 
96  return RPCHelpMan{
97  "getnewaddress",
98  "Returns a new Bitcoin address for receiving payments.\n"
99  "If 'label' is specified, it is added to the address book \n"
100  "so payments received with the address will be associated with "
101  "'label'.\n",
102  {
103  {"label", RPCArg::Type::STR, RPCArg::Default{""},
104  "The label name for the address to be linked to. If not provided, "
105  "the default label \"\" is used. It can also be set to the empty "
106  "string \"\" to represent the default label. The label does not "
107  "need to exist, it will be created if there is no label by the "
108  "given name."},
109  {"address_type", RPCArg::Type::STR,
110  RPCArg::DefaultHint{"set by -addresstype"},
111  "The address type to use. Options are \"legacy\"."},
112  },
113  RPCResult{RPCResult::Type::STR, "address", "The new bitcoin address"},
114  RPCExamples{HelpExampleCli("getnewaddress", "") +
115  HelpExampleRpc("getnewaddress", "")},
116  [&](const RPCHelpMan &self, const Config &config,
117  const JSONRPCRequest &request) -> UniValue {
118  std::shared_ptr<CWallet> const wallet =
120  if (!wallet) {
121  return NullUniValue;
122  }
123  CWallet *const pwallet = wallet.get();
124  LOCK(pwallet->cs_wallet);
125 
126  if (!pwallet->CanGetAddresses()) {
128  "Error: This wallet has no available keys");
129  }
130 
131  // Parse the label first so we don't generate a key if there's an
132  // error
133  std::string label;
134  if (!request.params[0].isNull()) {
135  label = LabelFromValue(request.params[0]);
136  }
137 
138  OutputType output_type = pwallet->m_default_address_type;
139  if (!request.params[1].isNull()) {
140  if (!ParseOutputType(request.params[1].get_str(),
141  output_type)) {
143  strprintf("Unknown address type '%s'",
144  request.params[1].get_str()));
145  }
146  }
147 
148  CTxDestination dest;
149  std::string error;
150  if (!pwallet->GetNewDestination(output_type, label, dest, error)) {
152  }
153 
154  return EncodeDestination(dest, config);
155  },
156  };
157 }
158 
160  return RPCHelpMan{
161  "getrawchangeaddress",
162  "Returns a new Bitcoin address, for receiving change.\n"
163  "This is for use with raw transactions, NOT normal use.\n",
164  {},
165  RPCResult{RPCResult::Type::STR, "address", "The address"},
166  RPCExamples{HelpExampleCli("getrawchangeaddress", "") +
167  HelpExampleRpc("getrawchangeaddress", "")},
168  [&](const RPCHelpMan &self, const Config &config,
169  const JSONRPCRequest &request) -> UniValue {
170  std::shared_ptr<CWallet> const wallet =
172  if (!wallet) {
173  return NullUniValue;
174  }
175  CWallet *const pwallet = wallet.get();
176 
177  LOCK(pwallet->cs_wallet);
178 
179  if (!pwallet->CanGetAddresses(true)) {
181  "Error: This wallet has no available keys");
182  }
183 
184  OutputType output_type = pwallet->m_default_change_type.value_or(
185  pwallet->m_default_address_type);
186  if (!request.params[0].isNull()) {
187  if (!ParseOutputType(request.params[0].get_str(),
188  output_type)) {
190  strprintf("Unknown address type '%s'",
191  request.params[0].get_str()));
192  }
193  }
194 
195  CTxDestination dest;
196  std::string error;
197  if (!pwallet->GetNewChangeDestination(output_type, dest, error)) {
199  }
200  return EncodeDestination(dest, config);
201  },
202  };
203 }
204 
206  return RPCHelpMan{
207  "setlabel",
208  "Sets the label associated with the given address.\n",
209  {
211  "The bitcoin address to be associated with a label."},
213  "The label to assign to the address."},
214  },
216  RPCExamples{
217  HelpExampleCli("setlabel",
218  "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"tabby\"") +
220  "setlabel",
221  "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"tabby\"")},
222  [&](const RPCHelpMan &self, const Config &config,
223  const JSONRPCRequest &request) -> UniValue {
224  std::shared_ptr<CWallet> const wallet =
226  if (!wallet) {
227  return NullUniValue;
228  }
229  CWallet *const pwallet = wallet.get();
230 
231  LOCK(pwallet->cs_wallet);
232 
233  CTxDestination dest = DecodeDestination(request.params[0].get_str(),
234  wallet->GetChainParams());
235  if (!IsValidDestination(dest)) {
237  "Invalid Bitcoin address");
238  }
239 
240  std::string label = LabelFromValue(request.params[1]);
241 
242  if (pwallet->IsMine(dest)) {
243  pwallet->SetAddressBook(dest, label, "receive");
244  } else {
245  pwallet->SetAddressBook(dest, label, "send");
246  }
247 
248  return NullUniValue;
249  },
250  };
251 }
252 
253 void ParseRecipients(const UniValue &address_amounts,
254  const UniValue &subtract_fee_outputs,
255  std::vector<CRecipient> &recipients,
256  const CChainParams &chainParams) {
257  std::set<CTxDestination> destinations;
258  int i = 0;
259  for (const std::string &address : address_amounts.getKeys()) {
260  CTxDestination dest = DecodeDestination(address, chainParams);
261  if (!IsValidDestination(dest)) {
263  std::string("Invalid Bitcoin address: ") +
264  address);
265  }
266 
267  if (destinations.count(dest)) {
268  throw JSONRPCError(
270  std::string("Invalid parameter, duplicated address: ") +
271  address);
272  }
273  destinations.insert(dest);
274 
275  CScript script_pub_key = GetScriptForDestination(dest);
276  Amount amount = AmountFromValue(address_amounts[i++]);
277 
278  bool subtract_fee = false;
279  for (unsigned int idx = 0; idx < subtract_fee_outputs.size(); idx++) {
280  const UniValue &addr = subtract_fee_outputs[idx];
281  if (addr.get_str() == address) {
282  subtract_fee = true;
283  }
284  }
285 
286  CRecipient recipient = {script_pub_key, amount, subtract_fee};
287  recipients.push_back(recipient);
288  }
289 }
290 
291 UniValue SendMoney(CWallet *const pwallet, const CCoinControl &coin_control,
292  std::vector<CRecipient> &recipients, mapValue_t map_value,
293  bool broadcast = true) {
294  EnsureWalletIsUnlocked(pwallet);
295 
296  // Shuffle recipient list
297  std::shuffle(recipients.begin(), recipients.end(), FastRandomContext());
298 
299  // Send
300  Amount nFeeRequired = Amount::zero();
301  int nChangePosRet = -1;
303  CTransactionRef tx;
304  bool fCreated = CreateTransaction(
305  *pwallet, recipients, tx, nFeeRequired, nChangePosRet, error,
306  coin_control,
308  if (!fCreated) {
310  }
311  pwallet->CommitTransaction(tx, std::move(map_value), {} /* orderForm */,
312  broadcast);
313  return tx->GetId().GetHex();
314 }
315 
317  return RPCHelpMan{
318  "sendtoaddress",
319  "Send an amount to a given address.\n" + HELP_REQUIRING_PASSPHRASE,
320  {
322  "The bitcoin address to send to."},
324  "The amount in " + Currency::get().ticker + " to send. eg 0.1"},
326  "A comment used to store what the transaction is for.\n"
327  " This is not part of the "
328  "transaction, just kept in your wallet."},
329  {"comment_to", RPCArg::Type::STR,
331  "A comment to store the name of the person or organization\n"
332  " to which you're sending the "
333  "transaction. This is not part of the \n"
334  " transaction, just kept in "
335  "your wallet."},
336  {"subtractfeefromamount", RPCArg::Type::BOOL,
337  RPCArg::Default{false},
338  "The fee will be deducted from the amount being sent.\n"
339  " The recipient will receive "
340  "less bitcoins than you enter in the amount field."},
341  {"avoid_reuse", RPCArg::Type::BOOL, RPCArg::Default{true},
342  "(only available if avoid_reuse wallet flag is set) Avoid "
343  "spending from dirty addresses; addresses are considered\n"
344  " dirty if they have previously "
345  "been used in a transaction."},
346  },
347  RPCResult{RPCResult::Type::STR_HEX, "txid", "The transaction id."},
348  RPCExamples{
349  HelpExampleCli("sendtoaddress",
350  "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 100000") +
351  HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvay"
352  "dd\" 100000 \"donation\" \"seans "
353  "outpost\"") +
354  HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44"
355  "Jvaydd\" 100000 \"\" \"\" true") +
356  HelpExampleRpc("sendtoaddress",
357  "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvay"
358  "dd\", 100000, \"donation\", \"seans "
359  "outpost\"")},
360  [&](const RPCHelpMan &self, const Config &config,
361  const JSONRPCRequest &request) -> UniValue {
362  std::shared_ptr<CWallet> const wallet =
364  if (!wallet) {
365  return NullUniValue;
366  }
367  CWallet *const pwallet = wallet.get();
368 
369  // Make sure the results are valid at least up to the most recent
370  // block the user could have gotten from another RPC command prior
371  // to now
372  pwallet->BlockUntilSyncedToCurrentChain();
373 
374  LOCK(pwallet->cs_wallet);
375 
376  // Wallet comments
377  mapValue_t mapValue;
378  if (!request.params[2].isNull() &&
379  !request.params[2].get_str().empty()) {
380  mapValue["comment"] = request.params[2].get_str();
381  }
382  if (!request.params[3].isNull() &&
383  !request.params[3].get_str().empty()) {
384  mapValue["to"] = request.params[3].get_str();
385  }
386 
387  bool fSubtractFeeFromAmount = false;
388  if (!request.params[4].isNull()) {
389  fSubtractFeeFromAmount = request.params[4].get_bool();
390  }
391 
392  CCoinControl coin_control;
393  coin_control.m_avoid_address_reuse =
394  GetAvoidReuseFlag(pwallet, request.params[5]);
395  // We also enable partial spend avoidance if reuse avoidance is set.
396  coin_control.m_avoid_partial_spends |=
397  coin_control.m_avoid_address_reuse;
398 
399  EnsureWalletIsUnlocked(pwallet);
400 
401  UniValue address_amounts(UniValue::VOBJ);
402  const std::string address = request.params[0].get_str();
403  address_amounts.pushKV(address, request.params[1]);
404  UniValue subtractFeeFromAmount(UniValue::VARR);
405  if (fSubtractFeeFromAmount) {
406  subtractFeeFromAmount.push_back(address);
407  }
408 
409  std::vector<CRecipient> recipients;
410  ParseRecipients(address_amounts, subtractFeeFromAmount, recipients,
411  wallet->GetChainParams());
412 
413  return SendMoney(pwallet, coin_control, recipients, mapValue);
414  },
415  };
416 }
417 
419  return RPCHelpMan{
420  "listaddressgroupings",
421  "Lists groups of addresses which have had their common ownership\n"
422  "made public by common use as inputs or as the resulting change\n"
423  "in past transactions\n",
424  {},
426  "",
427  "",
428  {
430  "",
431  "",
432  {
434  "",
435  "",
436  {
437  {RPCResult::Type::STR, "address",
438  "The bitcoin address"},
439  {RPCResult::Type::STR_AMOUNT, "amount",
440  "The amount in " + Currency::get().ticker},
441  {RPCResult::Type::STR, "label",
442  /* optional */ true, "The label"},
443  }},
444  }},
445  }},
446  RPCExamples{HelpExampleCli("listaddressgroupings", "") +
447  HelpExampleRpc("listaddressgroupings", "")},
448  [&](const RPCHelpMan &self, const Config &config,
449  const JSONRPCRequest &request) -> UniValue {
450  std::shared_ptr<CWallet> const wallet =
452  if (!wallet) {
453  return NullUniValue;
454  }
455  const CWallet *const pwallet = wallet.get();
456 
457  // Make sure the results are valid at least up to the most recent
458  // block the user could have gotten from another RPC command prior
459  // to now
460  pwallet->BlockUntilSyncedToCurrentChain();
461 
462  LOCK(pwallet->cs_wallet);
463 
464  UniValue jsonGroupings(UniValue::VARR);
465  std::map<CTxDestination, Amount> balances =
466  GetAddressBalances(*pwallet);
467  for (const std::set<CTxDestination> &grouping :
468  GetAddressGroupings(*pwallet)) {
469  UniValue jsonGrouping(UniValue::VARR);
470  for (const CTxDestination &address : grouping) {
471  UniValue addressInfo(UniValue::VARR);
472  addressInfo.push_back(EncodeDestination(address, config));
473  addressInfo.push_back(balances[address]);
474 
475  const auto *address_book_entry =
476  pwallet->FindAddressBookEntry(address);
477  if (address_book_entry) {
478  addressInfo.push_back(address_book_entry->GetLabel());
479  }
480  jsonGrouping.push_back(addressInfo);
481  }
482  jsonGroupings.push_back(jsonGrouping);
483  }
484 
485  return jsonGroupings;
486  },
487  };
488 }
489 
490 static Amount GetReceived(const CWallet &wallet, const UniValue &params,
491  bool by_label)
492  EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet) {
493  std::set<CTxDestination> address_set;
494 
495  if (by_label) {
496  // Get the set of addresses assigned to label
497  std::string label = LabelFromValue(params[0]);
498  address_set = wallet.GetLabelAddresses(label);
499  } else {
500  // Get the address
501  CTxDestination dest =
502  DecodeDestination(params[0].get_str(), wallet.GetChainParams());
503  if (!IsValidDestination(dest)) {
505  "Invalid Bitcoin address");
506  }
507  CScript script_pub_key = GetScriptForDestination(dest);
508  if (!wallet.IsMine(script_pub_key)) {
509  throw JSONRPCError(RPC_WALLET_ERROR, "Address not found in wallet");
510  }
511  address_set.insert(dest);
512  }
513 
514  // Minimum confirmations
515  int min_depth = 1;
516  if (!params[1].isNull()) {
517  min_depth = params[1].get_int();
518  }
519 
520  // Tally
521  Amount amount = Amount::zero();
522  for (const std::pair<const TxId, CWalletTx> &wtx_pair : wallet.mapWallet) {
523  const CWalletTx &wtx = wtx_pair.second;
524  if (wtx.IsCoinBase() || wallet.GetTxDepthInMainChain(wtx) < min_depth) {
525  continue;
526  }
527 
528  for (const CTxOut &txout : wtx.tx->vout) {
529  CTxDestination address;
530  if (ExtractDestination(txout.scriptPubKey, address) &&
531  wallet.IsMine(address) && address_set.count(address)) {
532  amount += txout.nValue;
533  }
534  }
535  }
536 
537  return amount;
538 }
539 
541  return RPCHelpMan{
542  "getreceivedbyaddress",
543  "Returns the total amount received by the given address in "
544  "transactions with at least minconf confirmations.\n",
545  {
547  "The bitcoin address for transactions."},
548  {"minconf", RPCArg::Type::NUM, RPCArg::Default{1},
549  "Only include transactions confirmed at least this many times."},
550  },
552  "The total amount in " + Currency::get().ticker +
553  " received at this address."},
554  RPCExamples{
555  "\nThe amount from transactions with at least 1 confirmation\n" +
556  HelpExampleCli("getreceivedbyaddress",
557  "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\"") +
558  "\nThe amount including unconfirmed transactions, zero "
559  "confirmations\n" +
560  HelpExampleCli("getreceivedbyaddress",
561  "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" 0") +
562  "\nThe amount with at least 6 confirmations\n" +
563  HelpExampleCli("getreceivedbyaddress",
564  "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" 6") +
565  "\nAs a JSON-RPC call\n" +
566  HelpExampleRpc("getreceivedbyaddress",
567  "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", 6")},
568  [&](const RPCHelpMan &self, const Config &config,
569  const JSONRPCRequest &request) -> UniValue {
570  std::shared_ptr<CWallet> const wallet =
572  if (!wallet) {
573  return NullUniValue;
574  }
575  const CWallet *const pwallet = wallet.get();
576 
577  // Make sure the results are valid at least up to the most recent
578  // block the user could have gotten from another RPC command prior
579  // to now
580  pwallet->BlockUntilSyncedToCurrentChain();
581 
582  LOCK(pwallet->cs_wallet);
583 
584  return GetReceived(*pwallet, request.params,
585  /* by_label */ false);
586  },
587  };
588 }
589 
591  return RPCHelpMan{
592  "getreceivedbylabel",
593  "Returns the total amount received by addresses with <label> in "
594  "transactions with at least [minconf] confirmations.\n",
595  {
597  "The selected label, may be the default label using \"\"."},
598  {"minconf", RPCArg::Type::NUM, RPCArg::Default{1},
599  "Only include transactions confirmed at least this many times."},
600  },
602  "The total amount in " + Currency::get().ticker +
603  " received for this label."},
604  RPCExamples{"\nAmount received by the default label with at least 1 "
605  "confirmation\n" +
606  HelpExampleCli("getreceivedbylabel", "\"\"") +
607  "\nAmount received at the tabby label including "
608  "unconfirmed amounts with zero confirmations\n" +
609  HelpExampleCli("getreceivedbylabel", "\"tabby\" 0") +
610  "\nThe amount with at least 6 confirmations\n" +
611  HelpExampleCli("getreceivedbylabel", "\"tabby\" 6") +
612  "\nAs a JSON-RPC call\n" +
613  HelpExampleRpc("getreceivedbylabel", "\"tabby\", 6")},
614  [&](const RPCHelpMan &self, const Config &config,
615  const JSONRPCRequest &request) -> UniValue {
616  std::shared_ptr<CWallet> const wallet =
618  if (!wallet) {
619  return NullUniValue;
620  }
621  CWallet *const pwallet = wallet.get();
622 
623  // Make sure the results are valid at least up to the most recent
624  // block the user could have gotten from another RPC command prior
625  // to now
626  pwallet->BlockUntilSyncedToCurrentChain();
627 
628  LOCK(pwallet->cs_wallet);
629 
630  return GetReceived(*pwallet, request.params,
631  /* by_label */ true);
632  },
633  };
634 }
635 
637  return RPCHelpMan{
638  "getbalance",
639  "Returns the total available balance.\n"
640  "The available balance is what the wallet considers currently "
641  "spendable, and is\n"
642  "thus affected by options which limit spendability such as "
643  "-spendzeroconfchange.\n",
644  {
646  "Remains for backward compatibility. Must be excluded or set to "
647  "\"*\"."},
648  {"minconf", RPCArg::Type::NUM, RPCArg::Default{0},
649  "Only include transactions confirmed at least this many times."},
650  {"include_watchonly", RPCArg::Type::BOOL,
652  "true for watch-only wallets, otherwise false"},
653  "Also include balance in watch-only addresses (see "
654  "'importaddress')"},
655  {"avoid_reuse", RPCArg::Type::BOOL, RPCArg::Default{true},
656  "(only available if avoid_reuse wallet flag is set) Do not "
657  "include balance in dirty outputs; addresses are considered dirty "
658  "if they have previously been used in a transaction."},
659  },
661  "The total amount in " + Currency::get().ticker +
662  " received for this wallet."},
663  RPCExamples{
664  "\nThe total amount in the wallet with 0 or more confirmations\n" +
665  HelpExampleCli("getbalance", "") +
666  "\nThe total amount in the wallet with at least 6 confirmations\n" +
667  HelpExampleCli("getbalance", "\"*\" 6") + "\nAs a JSON-RPC call\n" +
668  HelpExampleRpc("getbalance", "\"*\", 6")},
669  [&](const RPCHelpMan &self, const Config &config,
670  const JSONRPCRequest &request) -> UniValue {
671  std::shared_ptr<CWallet> const wallet =
673  if (!wallet) {
674  return NullUniValue;
675  }
676  const CWallet *const pwallet = wallet.get();
677 
678  // Make sure the results are valid at least up to the most recent
679  // block the user could have gotten from another RPC command prior
680  // to now
681  pwallet->BlockUntilSyncedToCurrentChain();
682 
683  LOCK(pwallet->cs_wallet);
684 
685  const UniValue &dummy_value = request.params[0];
686  if (!dummy_value.isNull() && dummy_value.get_str() != "*") {
687  throw JSONRPCError(
689  "dummy first argument must be excluded or set to \"*\".");
690  }
691 
692  int min_depth = 0;
693  if (!request.params[1].isNull()) {
694  min_depth = request.params[1].get_int();
695  }
696 
697  bool include_watchonly =
698  ParseIncludeWatchonly(request.params[2], *pwallet);
699 
700  bool avoid_reuse = GetAvoidReuseFlag(pwallet, request.params[3]);
701 
702  const auto bal = GetBalance(*pwallet, min_depth, avoid_reuse);
703 
704  return bal.m_mine_trusted + (include_watchonly
705  ? bal.m_watchonly_trusted
706  : Amount::zero());
707  },
708  };
709 }
710 
712  return RPCHelpMan{
713  "getunconfirmedbalance",
714  "DEPRECATED\nIdentical to getbalances().mine.untrusted_pending\n",
715  {},
716  RPCResult{RPCResult::Type::NUM, "", "The balance"},
717  RPCExamples{""},
718  [&](const RPCHelpMan &self, const Config &config,
719  const JSONRPCRequest &request) -> UniValue {
720  std::shared_ptr<CWallet> const wallet =
722  if (!wallet) {
723  return NullUniValue;
724  }
725  const CWallet *const pwallet = wallet.get();
726 
727  // Make sure the results are valid at least up to the most recent
728  // block the user could have gotten from another RPC command prior
729  // to now
730  pwallet->BlockUntilSyncedToCurrentChain();
731 
732  LOCK(pwallet->cs_wallet);
733 
734  return GetBalance(*pwallet).m_mine_untrusted_pending;
735  },
736  };
737 }
738 
740  return RPCHelpMan{
741  "sendmany",
742  "Send multiple times. Amounts are double-precision "
743  "floating point numbers." +
745  {
747  "Must be set to \"\" for backwards compatibility.",
749  .oneline_description = "\"\""}},
750  {
751  "amounts",
754  "The addresses and amounts",
755  {
757  "The bitcoin address is the key, the numeric amount (can "
758  "be string) in " +
759  Currency::get().ticker + " is the value"},
760  },
761  },
762  {"minconf", RPCArg::Type::NUM, RPCArg::Default{1},
763  "Only use the balance confirmed at least this many times."},
765  "A comment"},
766  {
767  "subtractfeefrom",
770  "The addresses.\n"
771  " The fee will be equally deducted "
772  "from the amount of each selected address.\n"
773  " Those recipients will receive less "
774  "bitcoins than you enter in their corresponding amount field.\n"
775  " If no addresses are specified "
776  "here, the sender pays the fee.",
777  {
779  "Subtract fee from this address"},
780  },
781  },
782  },
784  "The transaction id for the send. Only 1 transaction is "
785  "created regardless of the number of addresses."},
786  RPCExamples{
787  "\nSend two amounts to two different addresses:\n" +
789  "sendmany",
790  "\"\" "
791  "\"{\\\"bchtest:qplljx455cznj2yrtdhj0jcm7syxlzqnaqt0ku5kjl\\\":"
792  "0.01,"
793  "\\\"bchtest:qzmnuh8t24yrxq4mvjakt84r7j3f9tunlvm2p7qef9\\\":0."
794  "02}\"") +
795  "\nSend two amounts to two different addresses setting the "
796  "confirmation and comment:\n" +
798  "sendmany",
799  "\"\" "
800  "\"{\\\"bchtest:qplljx455cznj2yrtdhj0jcm7syxlzqnaqt0ku5kjl\\\":"
801  "0.01,"
802  "\\\"bchtest:qzmnuh8t24yrxq4mvjakt84r7j3f9tunlvm2p7qef9\\\":0."
803  "02}\" "
804  "6 \"testing\"") +
805  "\nSend two amounts to two different addresses, subtract fee "
806  "from amount:\n" +
808  "sendmany",
809  "\"\" "
810  "\"{\\\"bchtest:qplljx455cznj2yrtdhj0jcm7syxlzqnaqt0ku5kjl\\\":"
811  "0.01,"
812  "\\\"bchtest:qzmnuh8t24yrxq4mvjakt84r7j3f9tunlvm2p7qef9\\\":0."
813  "02}\" 1 \"\" "
814  "\"[\\\"bchtest:qplljx455cznj2yrtdhj0jcm7syxlzqnaqt0ku5kjl\\\","
815  "\\\"bchtest:qzmnuh8t24yrxq4mvjakt84r7j3f9tunlvm2p7qef9\\\"]"
816  "\"") +
817  "\nAs a JSON-RPC call\n" +
819  "sendmany",
820  "\"\", "
821  "{\"bchtest:qplljx455cznj2yrtdhj0jcm7syxlzqnaqt0ku5kjl\":0.01,"
822  "\"bchtest:qzmnuh8t24yrxq4mvjakt84r7j3f9tunlvm2p7qef9\":0.02}, "
823  "6, "
824  "\"testing\"")},
825  [&](const RPCHelpMan &self, const Config &config,
826  const JSONRPCRequest &request) -> UniValue {
827  std::shared_ptr<CWallet> const wallet =
829  if (!wallet) {
830  return NullUniValue;
831  }
832  CWallet *const pwallet = wallet.get();
833 
834  // Make sure the results are valid at least up to the most recent
835  // block the user could have gotten from another RPC command prior
836  // to now
837  pwallet->BlockUntilSyncedToCurrentChain();
838 
839  LOCK(pwallet->cs_wallet);
840 
841  if (!request.params[0].isNull() &&
842  !request.params[0].get_str().empty()) {
844  "Dummy value must be set to \"\"");
845  }
846  UniValue sendTo = request.params[1].get_obj();
847 
848  mapValue_t mapValue;
849  if (!request.params[3].isNull() &&
850  !request.params[3].get_str().empty()) {
851  mapValue["comment"] = request.params[3].get_str();
852  }
853 
854  UniValue subtractFeeFromAmount(UniValue::VARR);
855  if (!request.params[4].isNull()) {
856  subtractFeeFromAmount = request.params[4].get_array();
857  }
858 
859  std::vector<CRecipient> recipients;
860  ParseRecipients(sendTo, subtractFeeFromAmount, recipients,
861  wallet->GetChainParams());
862 
863  CCoinControl coin_control;
864  return SendMoney(pwallet, coin_control, recipients,
865  std::move(mapValue));
866  },
867  };
868 }
869 
871  return RPCHelpMan{
872  "addmultisigaddress",
873  "Add an nrequired-to-sign multisignature address to the wallet. "
874  "Requires a new wallet backup.\n"
875  "Each key is a Bitcoin address or hex-encoded public key.\n"
876  "This functionality is only intended for use with non-watchonly "
877  "addresses.\n"
878  "See `importaddress` for watchonly p2sh address support.\n"
879  "If 'label' is specified (DEPRECATED), assign address to that label.\n",
880  {
882  "The number of required signatures out of the n keys or "
883  "addresses."},
884  {
885  "keys",
888  "The bitcoin addresses or hex-encoded public keys",
889  {
891  "bitcoin address or hex-encoded public key"},
892  },
893  },
895  "A label to assign the addresses to."},
896  },
898  "",
899  "",
900  {
901  {RPCResult::Type::STR, "address",
902  "The value of the new multisig address"},
903  {RPCResult::Type::STR_HEX, "redeemScript",
904  "The string value of the hex-encoded redemption script"},
905  {RPCResult::Type::STR, "descriptor",
906  "The descriptor for this multisig"},
907  }},
908  RPCExamples{
909  "\nAdd a multisig address from 2 addresses\n" +
910  HelpExampleCli("addmultisigaddress",
911  "2 "
912  "\"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\","
913  "\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
914  "\nAs a JSON-RPC call\n" +
915  HelpExampleRpc("addmultisigaddress",
916  "2, "
917  "\"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\","
918  "\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")},
919  [&](const RPCHelpMan &self, const Config &config,
920  const JSONRPCRequest &request) -> UniValue {
921  std::shared_ptr<CWallet> const wallet =
923  if (!wallet) {
924  return NullUniValue;
925  }
926  CWallet *const pwallet = wallet.get();
927 
928  LegacyScriptPubKeyMan &spk_man =
929  EnsureLegacyScriptPubKeyMan(*pwallet);
930 
931  LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore);
932 
933  std::string label;
934  if (!request.params[2].isNull()) {
935  label = LabelFromValue(request.params[2]);
936  }
937 
938  int required = request.params[0].get_int();
939 
940  // Get the public keys
941  const UniValue &keys_or_addrs = request.params[1].get_array();
942  std::vector<CPubKey> pubkeys;
943  for (size_t i = 0; i < keys_or_addrs.size(); ++i) {
944  if (IsHex(keys_or_addrs[i].get_str()) &&
945  (keys_or_addrs[i].get_str().length() == 66 ||
946  keys_or_addrs[i].get_str().length() == 130)) {
947  pubkeys.push_back(HexToPubKey(keys_or_addrs[i].get_str()));
948  } else {
949  pubkeys.push_back(AddrToPubKey(wallet->GetChainParams(),
950  spk_man,
951  keys_or_addrs[i].get_str()));
952  }
953  }
954 
955  OutputType output_type = pwallet->m_default_address_type;
956 
957  // Construct using pay-to-script-hash:
958  CScript inner;
960  required, pubkeys, output_type, spk_man, inner);
961  pwallet->SetAddressBook(dest, label, "send");
962 
963  // Make the descriptor
964  std::unique_ptr<Descriptor> descriptor =
966 
967  UniValue result(UniValue::VOBJ);
968  result.pushKV("address", EncodeDestination(dest, config));
969  result.pushKV("redeemScript", HexStr(inner));
970  result.pushKV("descriptor", descriptor->ToString());
971  return result;
972  },
973  };
974 }
975 
976 struct tallyitem {
978  int nConf{std::numeric_limits<int>::max()};
979  std::vector<uint256> txids;
980  bool fIsWatchonly{false};
982 };
983 
984 static UniValue ListReceived(const Config &config, const CWallet *const pwallet,
985  const UniValue &params, bool by_label)
986  EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) {
987  // Minimum confirmations
988  int nMinDepth = 1;
989  if (!params[0].isNull()) {
990  nMinDepth = params[0].get_int();
991  }
992 
993  // Whether to include empty labels
994  bool fIncludeEmpty = false;
995  if (!params[1].isNull()) {
996  fIncludeEmpty = params[1].get_bool();
997  }
998 
1000  if (ParseIncludeWatchonly(params[2], *pwallet)) {
1001  filter |= ISMINE_WATCH_ONLY;
1002  }
1003 
1004  bool has_filtered_address = false;
1005  CTxDestination filtered_address = CNoDestination();
1006  if (!by_label && params.size() > 3) {
1007  if (!IsValidDestinationString(params[3].get_str(),
1008  pwallet->GetChainParams())) {
1010  "address_filter parameter was invalid");
1011  }
1012  filtered_address =
1013  DecodeDestination(params[3].get_str(), pwallet->GetChainParams());
1014  has_filtered_address = true;
1015  }
1016 
1017  // Tally
1018  std::map<CTxDestination, tallyitem> mapTally;
1019  for (const std::pair<const TxId, CWalletTx> &pairWtx : pwallet->mapWallet) {
1020  const CWalletTx &wtx = pairWtx.second;
1021 
1022  if (wtx.IsCoinBase()) {
1023  continue;
1024  }
1025 
1026  int nDepth = pwallet->GetTxDepthInMainChain(wtx);
1027  if (nDepth < nMinDepth) {
1028  continue;
1029  }
1030 
1031  for (const CTxOut &txout : wtx.tx->vout) {
1032  CTxDestination address;
1033  if (!ExtractDestination(txout.scriptPubKey, address)) {
1034  continue;
1035  }
1036 
1037  if (has_filtered_address && !(filtered_address == address)) {
1038  continue;
1039  }
1040 
1041  isminefilter mine = pwallet->IsMine(address);
1042  if (!(mine & filter)) {
1043  continue;
1044  }
1045 
1046  tallyitem &item = mapTally[address];
1047  item.nAmount += txout.nValue;
1048  item.nConf = std::min(item.nConf, nDepth);
1049  item.txids.push_back(wtx.GetId());
1050  if (mine & ISMINE_WATCH_ONLY) {
1051  item.fIsWatchonly = true;
1052  }
1053  }
1054  }
1055 
1056  // Reply
1057  UniValue ret(UniValue::VARR);
1058  std::map<std::string, tallyitem> label_tally;
1059 
1060  // Create m_address_book iterator
1061  // If we aren't filtering, go from begin() to end()
1062  auto start = pwallet->m_address_book.begin();
1063  auto end = pwallet->m_address_book.end();
1064  // If we are filtering, find() the applicable entry
1065  if (has_filtered_address) {
1066  start = pwallet->m_address_book.find(filtered_address);
1067  if (start != end) {
1068  end = std::next(start);
1069  }
1070  }
1071 
1072  for (auto item_it = start; item_it != end; ++item_it) {
1073  if (item_it->second.IsChange()) {
1074  continue;
1075  }
1076  const CTxDestination &address = item_it->first;
1077  const std::string &label = item_it->second.GetLabel();
1078  std::map<CTxDestination, tallyitem>::iterator it =
1079  mapTally.find(address);
1080  if (it == mapTally.end() && !fIncludeEmpty) {
1081  continue;
1082  }
1083 
1084  Amount nAmount = Amount::zero();
1085  int nConf = std::numeric_limits<int>::max();
1086  bool fIsWatchonly = false;
1087  if (it != mapTally.end()) {
1088  nAmount = (*it).second.nAmount;
1089  nConf = (*it).second.nConf;
1090  fIsWatchonly = (*it).second.fIsWatchonly;
1091  }
1092 
1093  if (by_label) {
1094  tallyitem &_item = label_tally[label];
1095  _item.nAmount += nAmount;
1096  _item.nConf = std::min(_item.nConf, nConf);
1097  _item.fIsWatchonly = fIsWatchonly;
1098  } else {
1099  UniValue obj(UniValue::VOBJ);
1100  if (fIsWatchonly) {
1101  obj.pushKV("involvesWatchonly", true);
1102  }
1103  obj.pushKV("address", EncodeDestination(address, config));
1104  obj.pushKV("amount", nAmount);
1105  obj.pushKV("confirmations",
1106  (nConf == std::numeric_limits<int>::max() ? 0 : nConf));
1107  obj.pushKV("label", label);
1108  UniValue transactions(UniValue::VARR);
1109  if (it != mapTally.end()) {
1110  for (const uint256 &_item : (*it).second.txids) {
1111  transactions.push_back(_item.GetHex());
1112  }
1113  }
1114  obj.pushKV("txids", transactions);
1115  ret.push_back(obj);
1116  }
1117  }
1118 
1119  if (by_label) {
1120  for (const auto &entry : label_tally) {
1121  Amount nAmount = entry.second.nAmount;
1122  int nConf = entry.second.nConf;
1123  UniValue obj(UniValue::VOBJ);
1124  if (entry.second.fIsWatchonly) {
1125  obj.pushKV("involvesWatchonly", true);
1126  }
1127  obj.pushKV("amount", nAmount);
1128  obj.pushKV("confirmations",
1129  (nConf == std::numeric_limits<int>::max() ? 0 : nConf));
1130  obj.pushKV("label", entry.first);
1131  ret.push_back(obj);
1132  }
1133  }
1134 
1135  return ret;
1136 }
1137 
1139  return RPCHelpMan{
1140  "listreceivedbyaddress",
1141  "List balances by receiving address.\n",
1142  {
1143  {"minconf", RPCArg::Type::NUM, RPCArg::Default{1},
1144  "The minimum number of confirmations before payments are "
1145  "included."},
1146  {"include_empty", RPCArg::Type::BOOL, RPCArg::Default{false},
1147  "Whether to include addresses that haven't received any "
1148  "payments."},
1149  {"include_watchonly", RPCArg::Type::BOOL,
1151  "true for watch-only wallets, otherwise false"},
1152  "Whether to include watch-only addresses (see 'importaddress')."},
1153  {"address_filter", RPCArg::Type::STR,
1155  "If present, only return information on this address."},
1156  },
1157  RPCResult{
1159  "",
1160  "",
1161  {
1163  "",
1164  "",
1165  {
1166  {RPCResult::Type::BOOL, "involvesWatchonly",
1167  "Only returns true if imported addresses were involved "
1168  "in transaction"},
1169  {RPCResult::Type::STR, "address", "The receiving address"},
1170  {RPCResult::Type::STR_AMOUNT, "amount",
1171  "The total amount in " + Currency::get().ticker +
1172  " received by the address"},
1173  {RPCResult::Type::NUM, "confirmations",
1174  "The number of confirmations of the most recent "
1175  "transaction included"},
1176  {RPCResult::Type::STR, "label",
1177  "The label of the receiving address. The default label "
1178  "is \"\""},
1180  "txids",
1181  "",
1182  {
1183  {RPCResult::Type::STR_HEX, "txid",
1184  "The ids of transactions received with the address"},
1185  }},
1186  }},
1187  }},
1188  RPCExamples{
1189  HelpExampleCli("listreceivedbyaddress", "") +
1190  HelpExampleCli("listreceivedbyaddress", "6 true") +
1191  HelpExampleRpc("listreceivedbyaddress", "6, true, true") +
1193  "listreceivedbyaddress",
1194  "6, true, true, \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\"")},
1195  [&](const RPCHelpMan &self, const Config &config,
1196  const JSONRPCRequest &request) -> UniValue {
1197  std::shared_ptr<CWallet> const wallet =
1198  GetWalletForJSONRPCRequest(request);
1199  if (!wallet) {
1200  return NullUniValue;
1201  }
1202  const CWallet *const pwallet = wallet.get();
1203 
1204  // Make sure the results are valid at least up to the most recent
1205  // block the user could have gotten from another RPC command prior
1206  // to now
1207  pwallet->BlockUntilSyncedToCurrentChain();
1208 
1209  LOCK(pwallet->cs_wallet);
1210 
1211  return ListReceived(config, pwallet, request.params, false);
1212  },
1213  };
1214 }
1215 
1217  return RPCHelpMan{
1218  "listreceivedbylabel",
1219  "List received transactions by label.\n",
1220  {
1221  {"minconf", RPCArg::Type::NUM, RPCArg::Default{1},
1222  "The minimum number of confirmations before payments are "
1223  "included."},
1224  {"include_empty", RPCArg::Type::BOOL, RPCArg::Default{false},
1225  "Whether to include labels that haven't received any payments."},
1226  {"include_watchonly", RPCArg::Type::BOOL,
1228  "true for watch-only wallets, otherwise false"},
1229  "Whether to include watch-only addresses (see 'importaddress')."},
1230  },
1231  RPCResult{
1233  "",
1234  "",
1235  {
1237  "",
1238  "",
1239  {
1240  {RPCResult::Type::BOOL, "involvesWatchonly",
1241  "Only returns true if imported addresses were involved "
1242  "in transaction"},
1243  {RPCResult::Type::STR_AMOUNT, "amount",
1244  "The total amount received by addresses with this label"},
1245  {RPCResult::Type::NUM, "confirmations",
1246  "The number of confirmations of the most recent "
1247  "transaction included"},
1248  {RPCResult::Type::STR, "label",
1249  "The label of the receiving address. The default label "
1250  "is \"\""},
1251  }},
1252  }},
1253  RPCExamples{HelpExampleCli("listreceivedbylabel", "") +
1254  HelpExampleCli("listreceivedbylabel", "6 true") +
1255  HelpExampleRpc("listreceivedbylabel", "6, true, true")},
1256  [&](const RPCHelpMan &self, const Config &config,
1257  const JSONRPCRequest &request) -> UniValue {
1258  std::shared_ptr<CWallet> const wallet =
1259  GetWalletForJSONRPCRequest(request);
1260  if (!wallet) {
1261  return NullUniValue;
1262  }
1263  const CWallet *const pwallet = wallet.get();
1264 
1265  // Make sure the results are valid at least up to the most recent
1266  // block the user could have gotten from another RPC command prior
1267  // to now
1268  pwallet->BlockUntilSyncedToCurrentChain();
1269 
1270  LOCK(pwallet->cs_wallet);
1271 
1272  return ListReceived(config, pwallet, request.params, true);
1273  },
1274  };
1275 }
1276 
1277 static void MaybePushAddress(UniValue &entry, const CTxDestination &dest) {
1278  if (IsValidDestination(dest)) {
1279  entry.pushKV("address", EncodeDestination(dest, GetConfig()));
1280  }
1281 }
1282 
1295 static void ListTransactions(const CWallet *const pwallet, const CWalletTx &wtx,
1296  int nMinDepth, bool fLong, UniValue &ret,
1297  const isminefilter &filter_ismine,
1298  const std::string *filter_label)
1299  EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) {
1300  Amount nFee;
1301  std::list<COutputEntry> listReceived;
1302  std::list<COutputEntry> listSent;
1303 
1304  CachedTxGetAmounts(*pwallet, wtx, listReceived, listSent, nFee,
1305  filter_ismine);
1306 
1307  bool involvesWatchonly = CachedTxIsFromMe(*pwallet, wtx, ISMINE_WATCH_ONLY);
1308 
1309  // Sent
1310  if (!filter_label) {
1311  for (const COutputEntry &s : listSent) {
1312  UniValue entry(UniValue::VOBJ);
1313  if (involvesWatchonly ||
1314  (pwallet->IsMine(s.destination) & ISMINE_WATCH_ONLY)) {
1315  entry.pushKV("involvesWatchonly", true);
1316  }
1317  MaybePushAddress(entry, s.destination);
1318  entry.pushKV("category", "send");
1319  entry.pushKV("amount", -s.amount);
1320  const auto *address_book_entry =
1321  pwallet->FindAddressBookEntry(s.destination);
1322  if (address_book_entry) {
1323  entry.pushKV("label", address_book_entry->GetLabel());
1324  }
1325  entry.pushKV("vout", s.vout);
1326  entry.pushKV("fee", -1 * nFee);
1327  if (fLong) {
1328  WalletTxToJSON(*pwallet, wtx, entry);
1329  }
1330  entry.pushKV("abandoned", wtx.isAbandoned());
1331  ret.push_back(entry);
1332  }
1333  }
1334 
1335  // Received
1336  if (listReceived.size() > 0 &&
1337  pwallet->GetTxDepthInMainChain(wtx) >= nMinDepth) {
1338  for (const COutputEntry &r : listReceived) {
1339  std::string label;
1340  const auto *address_book_entry =
1341  pwallet->FindAddressBookEntry(r.destination);
1342  if (address_book_entry) {
1343  label = address_book_entry->GetLabel();
1344  }
1345  if (filter_label && label != *filter_label) {
1346  continue;
1347  }
1348  UniValue entry(UniValue::VOBJ);
1349  if (involvesWatchonly ||
1350  (pwallet->IsMine(r.destination) & ISMINE_WATCH_ONLY)) {
1351  entry.pushKV("involvesWatchonly", true);
1352  }
1353  MaybePushAddress(entry, r.destination);
1354  if (wtx.IsCoinBase()) {
1355  if (pwallet->GetTxDepthInMainChain(wtx) < 1) {
1356  entry.pushKV("category", "orphan");
1357  } else if (pwallet->IsTxImmatureCoinBase(wtx)) {
1358  entry.pushKV("category", "immature");
1359  } else {
1360  entry.pushKV("category", "generate");
1361  }
1362  } else {
1363  entry.pushKV("category", "receive");
1364  }
1365  entry.pushKV("amount", r.amount);
1366  if (address_book_entry) {
1367  entry.pushKV("label", label);
1368  }
1369  entry.pushKV("vout", r.vout);
1370  if (fLong) {
1371  WalletTxToJSON(*pwallet, wtx, entry);
1372  }
1373  ret.push_back(entry);
1374  }
1375  }
1376 }
1377 
1378 static const std::vector<RPCResult> TransactionDescriptionString() {
1379  return {
1380  {RPCResult::Type::NUM, "confirmations",
1381  "The number of confirmations for the transaction. Negative "
1382  "confirmations means the\n"
1383  "transaction conflicted that many blocks ago."},
1384  {RPCResult::Type::BOOL, "generated",
1385  "Only present if transaction only input is a coinbase one."},
1386  {RPCResult::Type::BOOL, "trusted",
1387  "Only present if we consider transaction to be trusted and so safe to "
1388  "spend from."},
1389  {RPCResult::Type::STR_HEX, "blockhash",
1390  "The block hash containing the transaction."},
1391  {RPCResult::Type::NUM, "blockheight",
1392  "The block height containing the transaction."},
1393  {RPCResult::Type::NUM, "blockindex",
1394  "The index of the transaction in the block that includes it."},
1395  {RPCResult::Type::NUM_TIME, "blocktime",
1396  "The block time expressed in " + UNIX_EPOCH_TIME + "."},
1397  {RPCResult::Type::STR_HEX, "txid", "The transaction id."},
1399  "walletconflicts",
1400  "Conflicting transaction ids.",
1401  {
1402  {RPCResult::Type::STR_HEX, "txid", "The transaction id."},
1403  }},
1404  {RPCResult::Type::NUM_TIME, "time",
1405  "The transaction time expressed in " + UNIX_EPOCH_TIME + "."},
1406  {RPCResult::Type::NUM_TIME, "timereceived",
1407  "The time received expressed in " + UNIX_EPOCH_TIME + "."},
1408  {RPCResult::Type::STR, "comment",
1409  "If a comment is associated with the transaction, only present if not "
1410  "empty."},
1411  };
1412 }
1413 
1415  const auto &ticker = Currency::get().ticker;
1416  return RPCHelpMan{
1417  "listtransactions",
1418  "If a label name is provided, this will return only incoming "
1419  "transactions paying to addresses with the specified label.\n"
1420  "\nReturns up to 'count' most recent transactions skipping the first "
1421  "'from' transactions.\n",
1422  {
1423  {"label|dummy", RPCArg::Type::STR,
1425  "If set, should be a valid label name to return only incoming "
1426  "transactions with the specified label, or \"*\" to disable "
1427  "filtering and return all transactions."},
1428  {"count", RPCArg::Type::NUM, RPCArg::Default{10},
1429  "The number of transactions to return"},
1430  {"skip", RPCArg::Type::NUM, RPCArg::Default{0},
1431  "The number of transactions to skip"},
1432  {"include_watchonly", RPCArg::Type::BOOL,
1434  "true for watch-only wallets, otherwise false"},
1435  "Include transactions to watch-only addresses (see "
1436  "'importaddress')"},
1437  },
1438  RPCResult{
1440  "",
1441  "",
1442  {
1443  {RPCResult::Type::OBJ, "", "",
1444  Cat(Cat<std::vector<RPCResult>>(
1445  {
1446  {RPCResult::Type::BOOL, "involvesWatchonly",
1447  "Only returns true if imported addresses were "
1448  "involved in transaction."},
1449  {RPCResult::Type::STR, "address",
1450  "The bitcoin address of the transaction."},
1451  {RPCResult::Type::STR, "category",
1452  "The transaction category.\n"
1453  "\"send\" Transactions sent.\n"
1454  "\"receive\" Non-coinbase "
1455  "transactions received.\n"
1456  "\"generate\" Coinbase transactions "
1457  "received with more than 100 confirmations.\n"
1458  "\"immature\" Coinbase transactions "
1459  "received with 100 or fewer confirmations.\n"
1460  "\"orphan\" Orphaned coinbase "
1461  "transactions received."},
1462  {RPCResult::Type::STR_AMOUNT, "amount",
1463  "The amount in " + ticker +
1464  ". This is negative for the 'send' category, "
1465  "and is positive\n"
1466  "for all other categories"},
1467  {RPCResult::Type::STR, "label",
1468  "A comment for the address/transaction, if any"},
1469  {RPCResult::Type::NUM, "vout", "the vout value"},
1471  "The amount of the fee in " + ticker +
1472  ". This is negative and only available for "
1473  "the\n"
1474  "'send' category of transactions."},
1475  },
1477  {
1478  {RPCResult::Type::BOOL, "abandoned",
1479  "'true' if the transaction has been abandoned "
1480  "(inputs are respendable). Only available for the \n"
1481  "'send' category of transactions."},
1482  })},
1483  }},
1484  RPCExamples{"\nList the most recent 10 transactions in the systems\n" +
1485  HelpExampleCli("listtransactions", "") +
1486  "\nList transactions 100 to 120\n" +
1487  HelpExampleCli("listtransactions", "\"*\" 20 100") +
1488  "\nAs a JSON-RPC call\n" +
1489  HelpExampleRpc("listtransactions", "\"*\", 20, 100")},
1490  [&](const RPCHelpMan &self, const Config &config,
1491  const JSONRPCRequest &request) -> UniValue {
1492  std::shared_ptr<CWallet> const wallet =
1493  GetWalletForJSONRPCRequest(request);
1494  if (!wallet) {
1495  return NullUniValue;
1496  }
1497  const CWallet *const pwallet = wallet.get();
1498 
1499  // Make sure the results are valid at least up to the most recent
1500  // block the user could have gotten from another RPC command prior
1501  // to now
1502  pwallet->BlockUntilSyncedToCurrentChain();
1503 
1504  const std::string *filter_label = nullptr;
1505  if (!request.params[0].isNull() &&
1506  request.params[0].get_str() != "*") {
1507  filter_label = &request.params[0].get_str();
1508  if (filter_label->empty()) {
1509  throw JSONRPCError(
1511  "Label argument must be a valid label name or \"*\".");
1512  }
1513  }
1514  int nCount = 10;
1515  if (!request.params[1].isNull()) {
1516  nCount = request.params[1].get_int();
1517  }
1518 
1519  int nFrom = 0;
1520  if (!request.params[2].isNull()) {
1521  nFrom = request.params[2].get_int();
1522  }
1523 
1524  isminefilter filter = ISMINE_SPENDABLE;
1525  if (ParseIncludeWatchonly(request.params[3], *pwallet)) {
1526  filter |= ISMINE_WATCH_ONLY;
1527  }
1528 
1529  if (nCount < 0) {
1530  throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
1531  }
1532  if (nFrom < 0) {
1533  throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
1534  }
1535  UniValue ret(UniValue::VARR);
1536 
1537  {
1538  LOCK(pwallet->cs_wallet);
1539 
1540  const CWallet::TxItems &txOrdered = pwallet->wtxOrdered;
1541 
1542  // iterate backwards until we have nCount items to return:
1543  for (CWallet::TxItems::const_reverse_iterator it =
1544  txOrdered.rbegin();
1545  it != txOrdered.rend(); ++it) {
1546  CWalletTx *const pwtx = (*it).second;
1547  ListTransactions(pwallet, *pwtx, 0, true, ret, filter,
1548  filter_label);
1549  if (int(ret.size()) >= (nCount + nFrom)) {
1550  break;
1551  }
1552  }
1553  }
1554 
1555  // ret is newest to oldest
1556 
1557  if (nFrom > (int)ret.size()) {
1558  nFrom = ret.size();
1559  }
1560  if ((nFrom + nCount) > (int)ret.size()) {
1561  nCount = ret.size() - nFrom;
1562  }
1563 
1564  const std::vector<UniValue> &txs = ret.getValues();
1565  UniValue result{UniValue::VARR};
1566  // Return oldest to newest
1567  result.push_backV(
1568  {txs.rend() - nFrom - nCount, txs.rend() - nFrom});
1569  return result;
1570  },
1571  };
1572 }
1573 
1575  const auto &ticker = Currency::get().ticker;
1576  return RPCHelpMan{
1577  "listsinceblock",
1578  "Get all transactions in blocks since block [blockhash], or all "
1579  "transactions if omitted.\n"
1580  "If \"blockhash\" is no longer a part of the main chain, transactions "
1581  "from the fork point onward are included.\n"
1582  "Additionally, if include_removed is set, transactions affecting the "
1583  "wallet which were removed are returned in the \"removed\" array.\n",
1584  {
1585  {"blockhash", RPCArg::Type::STR,
1587  "If set, the block hash to list transactions since, otherwise "
1588  "list all transactions."},
1589  {"target_confirmations", RPCArg::Type::NUM, RPCArg::Default{1},
1590  "Return the nth block hash from the main chain. e.g. 1 would mean "
1591  "the best block hash. Note: this is not used as a filter, but "
1592  "only affects [lastblock] in the return value"},
1593  {"include_watchonly", RPCArg::Type::BOOL,
1595  "true for watch-only wallets, otherwise false"},
1596  "Include transactions to watch-only addresses (see "
1597  "'importaddress')"},
1598  {"include_removed", RPCArg::Type::BOOL, RPCArg::Default{true},
1599  "Show transactions that were removed due to a reorg in the "
1600  "\"removed\" array\n"
1601  " (not "
1602  "guaranteed to work on pruned nodes)"},
1603  },
1604  RPCResult{
1606  "",
1607  "",
1608  {
1610  "transactions",
1611  "",
1612  {
1613  {RPCResult::Type::OBJ, "", "",
1614  Cat(Cat<std::vector<RPCResult>>(
1615  {
1616  {RPCResult::Type::BOOL, "involvesWatchonly",
1617  "Only returns true if imported addresses "
1618  "were involved in transaction."},
1619  {RPCResult::Type::STR, "address",
1620  "The bitcoin address of the transaction."},
1621  {RPCResult::Type::STR, "category",
1622  "The transaction category.\n"
1623  "\"send\" Transactions "
1624  "sent.\n"
1625  "\"receive\" Non-coinbase "
1626  "transactions received.\n"
1627  "\"generate\" Coinbase "
1628  "transactions received with more than 100 "
1629  "confirmations.\n"
1630  "\"immature\" Coinbase "
1631  "transactions received with 100 or fewer "
1632  "confirmations.\n"
1633  "\"orphan\" Orphaned "
1634  "coinbase transactions received."},
1635  {RPCResult::Type::STR_AMOUNT, "amount",
1636  "The amount in " + ticker +
1637  ". This is negative for the 'send' "
1638  "category, and is positive\n"
1639  "for all other categories"},
1640  {RPCResult::Type::NUM, "vout",
1641  "the vout value"},
1643  "The amount of the fee in " + ticker +
1644  ". This is negative and only available "
1645  "for the\n"
1646  "'send' category of transactions."},
1647  },
1649  {
1650  {RPCResult::Type::BOOL, "abandoned",
1651  "'true' if the transaction has been abandoned "
1652  "(inputs are respendable). Only available for "
1653  "the \n"
1654  "'send' category of transactions."},
1655  {RPCResult::Type::STR, "comment",
1656  "If a comment is associated with the "
1657  "transaction."},
1658  {RPCResult::Type::STR, "label",
1659  "A comment for the address/transaction, if any"},
1660  {RPCResult::Type::STR, "to",
1661  "If a comment to is associated with the "
1662  "transaction."},
1663  })},
1664  }},
1666  "removed",
1667  "<structure is the same as \"transactions\" above, only "
1668  "present if include_removed=true>\n"
1669  "Note: transactions that were re-added in the active chain "
1670  "will appear as-is in this array, and may thus have a "
1671  "positive confirmation count.",
1672  {
1673  {RPCResult::Type::ELISION, "", ""},
1674  }},
1675  {RPCResult::Type::STR_HEX, "lastblock",
1676  "The hash of the block (target_confirmations-1) from the best "
1677  "block on the main chain, or the genesis hash if the "
1678  "referenced block does not exist yet. This is typically used "
1679  "to feed back into listsinceblock the next time you call it. "
1680  "So you would generally use a target_confirmations of say 6, "
1681  "so you will be continually re-notified of transactions until "
1682  "they've reached 6 confirmations plus any new ones"},
1683  }},
1684  RPCExamples{HelpExampleCli("listsinceblock", "") +
1685  HelpExampleCli("listsinceblock",
1686  "\"000000000000000bacf66f7497b7dc45ef753ee9a"
1687  "7d38571037cdb1a57f663ad\" 6") +
1688  HelpExampleRpc("listsinceblock",
1689  "\"000000000000000bacf66f7497b7dc45ef753ee9a"
1690  "7d38571037cdb1a57f663ad\", 6")},
1691  [&](const RPCHelpMan &self, const Config &config,
1692  const JSONRPCRequest &request) -> UniValue {
1693  std::shared_ptr<CWallet> const pwallet =
1694  GetWalletForJSONRPCRequest(request);
1695 
1696  if (!pwallet) {
1697  return NullUniValue;
1698  }
1699 
1700  const CWallet &wallet = *pwallet;
1701  // Make sure the results are valid at least up to the most recent
1702  // block the user could have gotten from another RPC command prior
1703  // to now
1704  wallet.BlockUntilSyncedToCurrentChain();
1705 
1706  LOCK(wallet.cs_wallet);
1707 
1708  // Height of the specified block or the common ancestor, if the
1709  // block provided was in a deactivated chain.
1710  std::optional<int> height;
1711 
1712  // Height of the specified block, even if it's in a deactivated
1713  // chain.
1714  std::optional<int> altheight;
1715  int target_confirms = 1;
1716  isminefilter filter = ISMINE_SPENDABLE;
1717 
1718  BlockHash blockId;
1719  if (!request.params[0].isNull() &&
1720  !request.params[0].get_str().empty()) {
1721  blockId = BlockHash(ParseHashV(request.params[0], "blockhash"));
1722  height = int{};
1723  altheight = int{};
1724  if (!wallet.chain().findCommonAncestor(
1725  blockId, wallet.GetLastBlockHash(),
1726  /* ancestor out */ FoundBlock().height(*height),
1727  /* blockId out */ FoundBlock().height(*altheight))) {
1729  "Block not found");
1730  }
1731  }
1732 
1733  if (!request.params[1].isNull()) {
1734  target_confirms = request.params[1].get_int();
1735 
1736  if (target_confirms < 1) {
1738  "Invalid parameter");
1739  }
1740  }
1741 
1742  if (ParseIncludeWatchonly(request.params[2], wallet)) {
1743  filter |= ISMINE_WATCH_ONLY;
1744  }
1745 
1746  bool include_removed =
1747  (request.params[3].isNull() || request.params[3].get_bool());
1748 
1749  int depth = height ? wallet.GetLastBlockHeight() + 1 - *height : -1;
1750 
1751  UniValue transactions(UniValue::VARR);
1752 
1753  for (const std::pair<const TxId, CWalletTx> &pairWtx :
1754  wallet.mapWallet) {
1755  const CWalletTx &tx = pairWtx.second;
1756 
1757  if (depth == -1 || wallet.GetTxDepthInMainChain(tx) < depth) {
1758  ListTransactions(&wallet, tx, 0, true, transactions, filter,
1759  nullptr /* filter_label */);
1760  }
1761  }
1762 
1763  // when a reorg'd block is requested, we also list any relevant
1764  // transactions in the blocks of the chain that was detached
1765  UniValue removed(UniValue::VARR);
1766  while (include_removed && altheight && *altheight > *height) {
1767  CBlock block;
1768  if (!wallet.chain().findBlock(blockId,
1769  FoundBlock().data(block)) ||
1770  block.IsNull()) {
1772  "Can't read block from disk");
1773  }
1774  for (const CTransactionRef &tx : block.vtx) {
1775  auto it = wallet.mapWallet.find(tx->GetId());
1776  if (it != wallet.mapWallet.end()) {
1777  // We want all transactions regardless of confirmation
1778  // count to appear here, even negative confirmation
1779  // ones, hence the big negative.
1780  ListTransactions(&wallet, it->second, -100000000, true,
1781  removed, filter,
1782  nullptr /* filter_label */);
1783  }
1784  }
1785  blockId = block.hashPrevBlock;
1786  --*altheight;
1787  }
1788 
1789  BlockHash lastblock;
1790  target_confirms =
1791  std::min(target_confirms, wallet.GetLastBlockHeight() + 1);
1792  CHECK_NONFATAL(wallet.chain().findAncestorByHeight(
1793  wallet.GetLastBlockHash(),
1794  wallet.GetLastBlockHeight() + 1 - target_confirms,
1795  FoundBlock().hash(lastblock)));
1796 
1797  UniValue ret(UniValue::VOBJ);
1798  ret.pushKV("transactions", transactions);
1799  if (include_removed) {
1800  ret.pushKV("removed", removed);
1801  }
1802  ret.pushKV("lastblock", lastblock.GetHex());
1803 
1804  return ret;
1805  },
1806  };
1807 }
1808 
1810  const auto &ticker = Currency::get().ticker;
1811  return RPCHelpMan{
1812  "gettransaction",
1813  "Get detailed information about in-wallet transaction <txid>\n",
1814  {
1816  "The transaction id"},
1817  {"include_watchonly", RPCArg::Type::BOOL,
1819  "true for watch-only wallets, otherwise false"},
1820  "Whether to include watch-only addresses in balance calculation "
1821  "and details[]"},
1822  {"verbose", RPCArg::Type::BOOL, RPCArg::Default{false},
1823  "Whether to include a `decoded` field containing the decoded "
1824  "transaction (equivalent to RPC decoderawtransaction)"},
1825  },
1826  RPCResult{
1827  RPCResult::Type::OBJ, "", "",
1828  Cat(Cat<std::vector<RPCResult>>(
1829  {
1830  {RPCResult::Type::STR_AMOUNT, "amount",
1831  "The amount in " + ticker},
1833  "The amount of the fee in " + ticker +
1834  ". This is negative and only available for the\n"
1835  "'send' category of transactions."},
1836  },
1838  {
1840  "details",
1841  "",
1842  {
1844  "",
1845  "",
1846  {
1847  {RPCResult::Type::BOOL, "involvesWatchonly",
1848  "Only returns true if imported addresses were "
1849  "involved in transaction."},
1850  {RPCResult::Type::STR, "address",
1851  "The bitcoin address involved in the "
1852  "transaction."},
1853  {RPCResult::Type::STR, "category",
1854  "The transaction category.\n"
1855  "\"send\" Transactions sent.\n"
1856  "\"receive\" Non-coinbase "
1857  "transactions received.\n"
1858  "\"generate\" Coinbase "
1859  "transactions received with more than 100 "
1860  "confirmations.\n"
1861  "\"immature\" Coinbase "
1862  "transactions received with 100 or fewer "
1863  "confirmations.\n"
1864  "\"orphan\" Orphaned coinbase "
1865  "transactions received."},
1866  {RPCResult::Type::STR_AMOUNT, "amount",
1867  "The amount in " + ticker},
1868  {RPCResult::Type::STR, "label",
1869  "A comment for the address/transaction, if any"},
1870  {RPCResult::Type::NUM, "vout", "the vout value"},
1872  "The amount of the fee in " + ticker +
1873  ". This is negative and only available for "
1874  "the \n"
1875  "'send' category of transactions."},
1876  {RPCResult::Type::BOOL, "abandoned",
1877  "'true' if the transaction has been abandoned "
1878  "(inputs are respendable). Only available for "
1879  "the \n"
1880  "'send' category of transactions."},
1881  }},
1882  }},
1883  {RPCResult::Type::STR_HEX, "hex",
1884  "Raw data for transaction"},
1886  "decoded",
1887  "Optional, the decoded transaction (only present when "
1888  "`verbose` is passed)",
1889  {
1891  "Equivalent to the RPC decoderawtransaction method, "
1892  "or the RPC getrawtransaction method when `verbose` "
1893  "is passed."},
1894  }},
1895  })},
1896  RPCExamples{HelpExampleCli("gettransaction",
1897  "\"1075db55d416d3ca199f55b6084e2115b9345e16c"
1898  "5cf302fc80e9d5fbf5d48d\"") +
1899  HelpExampleCli("gettransaction",
1900  "\"1075db55d416d3ca199f55b6084e2115b9345e16c"
1901  "5cf302fc80e9d5fbf5d48d\" true") +
1902  HelpExampleCli("gettransaction",
1903  "\"1075db55d416d3ca199f55b6084e2115b9345e16c"
1904  "5cf302fc80e9d5fbf5d48d\" false true") +
1905  HelpExampleRpc("gettransaction",
1906  "\"1075db55d416d3ca199f55b6084e2115b9345e16c"
1907  "5cf302fc80e9d5fbf5d48d\"")},
1908  [&](const RPCHelpMan &self, const Config &config,
1909  const JSONRPCRequest &request) -> UniValue {
1910  std::shared_ptr<CWallet> const wallet =
1911  GetWalletForJSONRPCRequest(request);
1912  if (!wallet) {
1913  return NullUniValue;
1914  }
1915  const CWallet *const pwallet = wallet.get();
1916 
1917  // Make sure the results are valid at least up to the most recent
1918  // block the user could have gotten from another RPC command prior
1919  // to now
1920  pwallet->BlockUntilSyncedToCurrentChain();
1921 
1922  LOCK(pwallet->cs_wallet);
1923 
1924  TxId txid(ParseHashV(request.params[0], "txid"));
1925 
1926  isminefilter filter = ISMINE_SPENDABLE;
1927  if (ParseIncludeWatchonly(request.params[1], *pwallet)) {
1928  filter |= ISMINE_WATCH_ONLY;
1929  }
1930 
1931  bool verbose = request.params[2].isNull()
1932  ? false
1933  : request.params[2].get_bool();
1934 
1935  UniValue entry(UniValue::VOBJ);
1936  auto it = pwallet->mapWallet.find(txid);
1937  if (it == pwallet->mapWallet.end()) {
1939  "Invalid or non-wallet transaction id");
1940  }
1941  const CWalletTx &wtx = it->second;
1942 
1943  Amount nCredit = CachedTxGetCredit(*pwallet, wtx, filter);
1944  Amount nDebit = CachedTxGetDebit(*pwallet, wtx, filter);
1945  Amount nNet = nCredit - nDebit;
1946  Amount nFee = (CachedTxIsFromMe(*pwallet, wtx, filter)
1947  ? wtx.tx->GetValueOut() - nDebit
1948  : Amount::zero());
1949 
1950  entry.pushKV("amount", nNet - nFee);
1951  if (CachedTxIsFromMe(*pwallet, wtx, filter)) {
1952  entry.pushKV("fee", nFee);
1953  }
1954 
1955  WalletTxToJSON(*pwallet, wtx, entry);
1956 
1957  UniValue details(UniValue::VARR);
1958  ListTransactions(pwallet, wtx, 0, false, details, filter,
1959  nullptr /* filter_label */);
1960  entry.pushKV("details", details);
1961 
1962  std::string strHex =
1963  EncodeHexTx(*wtx.tx, pwallet->chain().rpcSerializationFlags());
1964  entry.pushKV("hex", strHex);
1965 
1966  if (verbose) {
1967  UniValue decoded(UniValue::VOBJ);
1968  TxToUniv(*wtx.tx, BlockHash(), decoded, false);
1969  entry.pushKV("decoded", decoded);
1970  }
1971 
1972  return entry;
1973  },
1974  };
1975 }
1976 
1978  return RPCHelpMan{
1979  "abandontransaction",
1980  "Mark in-wallet transaction <txid> as abandoned\n"
1981  "This will mark this transaction and all its in-wallet descendants as "
1982  "abandoned which will allow\n"
1983  "for their inputs to be respent. It can be used to replace \"stuck\" "
1984  "or evicted transactions.\n"
1985  "It only works on transactions which are not included in a block and "
1986  "are not currently in the mempool.\n"
1987  "It has no effect on transactions which are already abandoned.\n",
1988  {
1990  "The transaction id"},
1991  },
1993  RPCExamples{HelpExampleCli("abandontransaction",
1994  "\"1075db55d416d3ca199f55b6084e2115b9345e16c"
1995  "5cf302fc80e9d5fbf5d48d\"") +
1996  HelpExampleRpc("abandontransaction",
1997  "\"1075db55d416d3ca199f55b6084e2115b9345e16c"
1998  "5cf302fc80e9d5fbf5d48d\"")},
1999  [&](const RPCHelpMan &self, const Config &config,
2000  const JSONRPCRequest &request) -> UniValue {
2001  std::shared_ptr<CWallet> const wallet =
2002  GetWalletForJSONRPCRequest(request);
2003  if (!wallet) {
2004  return NullUniValue;
2005  }
2006  CWallet *const pwallet = wallet.get();
2007 
2008  // Make sure the results are valid at least up to the most recent
2009  // block the user could have gotten from another RPC command prior
2010  // to now
2011  pwallet->BlockUntilSyncedToCurrentChain();
2012 
2013  LOCK(pwallet->cs_wallet);
2014 
2015  TxId txid(ParseHashV(request.params[0], "txid"));
2016 
2017  if (!pwallet->mapWallet.count(txid)) {
2019  "Invalid or non-wallet transaction id");
2020  }
2021 
2022  if (!pwallet->AbandonTransaction(txid)) {
2024  "Transaction not eligible for abandonment");
2025  }
2026 
2027  return NullUniValue;
2028  },
2029  };
2030 }
2031 
2033  return RPCHelpMan{
2034  "keypoolrefill",
2035  "Fills the keypool." + HELP_REQUIRING_PASSPHRASE,
2036  {
2037  {"newsize", RPCArg::Type::NUM, RPCArg::Default{100},
2038  "The new keypool size"},
2039  },
2041  RPCExamples{HelpExampleCli("keypoolrefill", "") +
2042  HelpExampleRpc("keypoolrefill", "")},
2043  [&](const RPCHelpMan &self, const Config &config,
2044  const JSONRPCRequest &request) -> UniValue {
2045  std::shared_ptr<CWallet> const wallet =
2046  GetWalletForJSONRPCRequest(request);
2047  if (!wallet) {
2048  return NullUniValue;
2049  }
2050  CWallet *const pwallet = wallet.get();
2051 
2052  if (pwallet->IsLegacy() &&
2054  throw JSONRPCError(
2056  "Error: Private keys are disabled for this wallet");
2057  }
2058 
2059  LOCK(pwallet->cs_wallet);
2060 
2061  // 0 is interpreted by TopUpKeyPool() as the default keypool size
2062  // given by -keypool
2063  unsigned int kpSize = 0;
2064  if (!request.params[0].isNull()) {
2065  if (request.params[0].get_int() < 0) {
2066  throw JSONRPCError(
2068  "Invalid parameter, expected valid size.");
2069  }
2070  kpSize = (unsigned int)request.params[0].get_int();
2071  }
2072 
2073  EnsureWalletIsUnlocked(pwallet);
2074  pwallet->TopUpKeyPool(kpSize);
2075 
2076  if (pwallet->GetKeyPoolSize() < kpSize) {
2078  "Error refreshing keypool.");
2079  }
2080 
2081  return NullUniValue;
2082  },
2083  };
2084 }
2085 
2087  return RPCHelpMan{
2088  "lockunspent",
2089  "Updates list of temporarily unspendable outputs.\n"
2090  "Temporarily lock (unlock=false) or unlock (unlock=true) specified "
2091  "transaction outputs.\n"
2092  "If no transaction outputs are specified when unlocking then all "
2093  "current locked transaction outputs are unlocked.\n"
2094  "A locked transaction output will not be chosen by automatic coin "
2095  "selection, when spending bitcoins.\n"
2096  "Manually selected coins are automatically unlocked.\n"
2097  "Locks are stored in memory only. Nodes start with zero locked "
2098  "outputs, and the locked output list\n"
2099  "is always cleared (by virtue of process exit) when a node stops or "
2100  "fails.\n"
2101  "Also see the listunspent call\n",
2102  {
2104  "Whether to unlock (true) or lock (false) the specified "
2105  "transactions"},
2106  {
2107  "transactions",
2110  "The transaction outputs and within each, txid (string) vout "
2111  "(numeric).",
2112  {
2113  {
2114  "",
2117  "",
2118  {
2119  {"txid", RPCArg::Type::STR_HEX,
2120  RPCArg::Optional::NO, "The transaction id"},
2122  "The output number"},
2123  },
2124  },
2125  },
2126  },
2127  },
2129  "Whether the command was successful or not"},
2130  RPCExamples{
2131  "\nList the unspent transactions\n" +
2132  HelpExampleCli("listunspent", "") +
2133  "\nLock an unspent transaction\n" +
2134  HelpExampleCli("lockunspent", "false "
2135  "\"[{\\\"txid\\\":"
2136  "\\\"a08e6907dbbd3d809776dbfc5d82e371"
2137  "b764ed838b5655e72f463568df1aadf0\\\""
2138  ",\\\"vout\\\":1}]\"") +
2139  "\nList the locked transactions\n" +
2140  HelpExampleCli("listlockunspent", "") +
2141  "\nUnlock the transaction again\n" +
2142  HelpExampleCli("lockunspent", "true "
2143  "\"[{\\\"txid\\\":"
2144  "\\\"a08e6907dbbd3d809776dbfc5d82e371"
2145  "b764ed838b5655e72f463568df1aadf0\\\""
2146  ",\\\"vout\\\":1}]\"") +
2147  "\nAs a JSON-RPC call\n" +
2148  HelpExampleRpc("lockunspent", "false, "
2149  "\"[{\\\"txid\\\":"
2150  "\\\"a08e6907dbbd3d809776dbfc5d82e371"
2151  "b764ed838b5655e72f463568df1aadf0\\\""
2152  ",\\\"vout\\\":1}]\"")},
2153  [&](const RPCHelpMan &self, const Config &config,
2154  const JSONRPCRequest &request) -> UniValue {
2155  std::shared_ptr<CWallet> const wallet =
2156  GetWalletForJSONRPCRequest(request);
2157  if (!wallet) {
2158  return NullUniValue;
2159  }
2160  CWallet *const pwallet = wallet.get();
2161 
2162  // Make sure the results are valid at least up to the most recent
2163  // block the user could have gotten from another RPC command prior
2164  // to now
2165  pwallet->BlockUntilSyncedToCurrentChain();
2166 
2167  LOCK(pwallet->cs_wallet);
2168 
2169  RPCTypeCheckArgument(request.params[0], UniValue::VBOOL);
2170 
2171  bool fUnlock = request.params[0].get_bool();
2172 
2173  if (request.params[1].isNull()) {
2174  if (fUnlock) {
2175  pwallet->UnlockAllCoins();
2176  }
2177  return true;
2178  }
2179 
2180  RPCTypeCheckArgument(request.params[1], UniValue::VARR);
2181 
2182  const UniValue &output_params = request.params[1];
2183 
2184  // Create and validate the COutPoints first.
2185 
2186  std::vector<COutPoint> outputs;
2187  outputs.reserve(output_params.size());
2188 
2189  for (size_t idx = 0; idx < output_params.size(); idx++) {
2190  const UniValue &o = output_params[idx].get_obj();
2191 
2192  RPCTypeCheckObj(o, {
2193  {"txid", UniValueType(UniValue::VSTR)},
2194  {"vout", UniValueType(UniValue::VNUM)},
2195  });
2196 
2197  const int nOutput = o.find_value("vout").get_int();
2198  if (nOutput < 0) {
2199  throw JSONRPCError(
2201  "Invalid parameter, vout cannot be negative");
2202  }
2203 
2204  const TxId txid(ParseHashO(o, "txid"));
2205  const auto it = pwallet->mapWallet.find(txid);
2206  if (it == pwallet->mapWallet.end()) {
2207  throw JSONRPCError(
2209  "Invalid parameter, unknown transaction");
2210  }
2211 
2212  const COutPoint output(txid, nOutput);
2213  const CWalletTx &trans = it->second;
2214  if (output.GetN() >= trans.tx->vout.size()) {
2215  throw JSONRPCError(
2217  "Invalid parameter, vout index out of bounds");
2218  }
2219 
2220  if (pwallet->IsSpent(output)) {
2221  throw JSONRPCError(
2223  "Invalid parameter, expected unspent output");
2224  }
2225 
2226  const bool is_locked = pwallet->IsLockedCoin(output);
2227  if (fUnlock && !is_locked) {
2228  throw JSONRPCError(
2230  "Invalid parameter, expected locked output");
2231  }
2232 
2233  if (!fUnlock && is_locked) {
2234  throw JSONRPCError(
2236  "Invalid parameter, output already locked");
2237  }
2238 
2239  outputs.push_back(output);
2240  }
2241 
2242  // Atomically set (un)locked status for the outputs.
2243  for (const COutPoint &output : outputs) {
2244  if (fUnlock) {
2245  pwallet->UnlockCoin(output);
2246  } else {
2247  pwallet->LockCoin(output);
2248  }
2249  }
2250 
2251  return true;
2252  },
2253  };
2254 }
2255 
2257  return RPCHelpMan{
2258  "listlockunspent",
2259  "Returns list of temporarily unspendable outputs.\n"
2260  "See the lockunspent call to lock and unlock transactions for "
2261  "spending.\n",
2262  {},
2264  "",
2265  "",
2266  {
2268  "",
2269  "",
2270  {
2271  {RPCResult::Type::STR_HEX, "txid",
2272  "The transaction id locked"},
2273  {RPCResult::Type::NUM, "vout", "The vout value"},
2274  }},
2275  }},
2276  RPCExamples{
2277  "\nList the unspent transactions\n" +
2278  HelpExampleCli("listunspent", "") +
2279  "\nLock an unspent transaction\n" +
2280  HelpExampleCli("lockunspent", "false "
2281  "\"[{\\\"txid\\\":"
2282  "\\\"a08e6907dbbd3d809776dbfc5d82e371"
2283  "b764ed838b5655e72f463568df1aadf0\\\""
2284  ",\\\"vout\\\":1}]\"") +
2285  "\nList the locked transactions\n" +
2286  HelpExampleCli("listlockunspent", "") +
2287  "\nUnlock the transaction again\n" +
2288  HelpExampleCli("lockunspent", "true "
2289  "\"[{\\\"txid\\\":"
2290  "\\\"a08e6907dbbd3d809776dbfc5d82e371"
2291  "b764ed838b5655e72f463568df1aadf0\\\""
2292  ",\\\"vout\\\":1}]\"") +
2293  "\nAs a JSON-RPC call\n" + HelpExampleRpc("listlockunspent", "")},
2294  [&](const RPCHelpMan &self, const Config &config,
2295  const JSONRPCRequest &request) -> UniValue {
2296  std::shared_ptr<CWallet> const wallet =
2297  GetWalletForJSONRPCRequest(request);
2298  if (!wallet) {
2299  return NullUniValue;
2300  }
2301  const CWallet *const pwallet = wallet.get();
2302 
2303  LOCK(pwallet->cs_wallet);
2304 
2305  std::vector<COutPoint> vOutpts;
2306  pwallet->ListLockedCoins(vOutpts);
2307 
2308  UniValue ret(UniValue::VARR);
2309 
2310  for (const COutPoint &output : vOutpts) {
2312 
2313  o.pushKV("txid", output.GetTxId().GetHex());
2314  o.pushKV("vout", int(output.GetN()));
2315  ret.push_back(o);
2316  }
2317 
2318  return ret;
2319  },
2320  };
2321 }
2322 
2324  return RPCHelpMan{
2325  "settxfee",
2326  "Set the transaction fee per kB for this wallet. Overrides the "
2327  "global -paytxfee command line parameter.\n"
2328  "Can be deactivated by passing 0 as the fee. In that case automatic "
2329  "fee selection will be used by default.\n",
2330  {
2332  "The transaction fee in " + Currency::get().ticker + "/kB"},
2333  },
2334  RPCResult{RPCResult::Type::BOOL, "", "Returns true if successful"},
2335  RPCExamples{HelpExampleCli("settxfee", "0.00001") +
2336  HelpExampleRpc("settxfee", "0.00001")},
2337  [&](const RPCHelpMan &self, const Config &config,
2338  const JSONRPCRequest &request) -> UniValue {
2339  std::shared_ptr<CWallet> const wallet =
2340  GetWalletForJSONRPCRequest(request);
2341  if (!wallet) {
2342  return NullUniValue;
2343  }
2344  CWallet *const pwallet = wallet.get();
2345 
2346  LOCK(pwallet->cs_wallet);
2347 
2348  Amount nAmount = AmountFromValue(request.params[0]);
2349  CFeeRate tx_fee_rate(nAmount, 1000);
2350  CFeeRate max_tx_fee_rate(pwallet->m_default_max_tx_fee, 1000);
2351  if (tx_fee_rate == CFeeRate()) {
2352  // automatic selection
2353  } else if (tx_fee_rate < pwallet->chain().relayMinFee()) {
2354  throw JSONRPCError(
2356  strprintf("txfee cannot be less than min relay tx fee (%s)",
2357  pwallet->chain().relayMinFee().ToString()));
2358  } else if (tx_fee_rate < pwallet->m_min_fee) {
2359  throw JSONRPCError(
2361  strprintf("txfee cannot be less than wallet min fee (%s)",
2362  pwallet->m_min_fee.ToString()));
2363  } else if (tx_fee_rate > max_tx_fee_rate) {
2364  throw JSONRPCError(
2366  strprintf(
2367  "txfee cannot be more than wallet max tx fee (%s)",
2368  max_tx_fee_rate.ToString()));
2369  }
2370 
2371  pwallet->m_pay_tx_fee = tx_fee_rate;
2372  return true;
2373  },
2374  };
2375 }
2376 
2378  return RPCHelpMan{
2379  "getbalances",
2380  "Returns an object with all balances in " + Currency::get().ticker +
2381  ".\n",
2382  {},
2384  "",
2385  "",
2386  {
2388  "mine",
2389  "balances from outputs that the wallet can sign",
2390  {
2391  {RPCResult::Type::STR_AMOUNT, "trusted",
2392  "trusted balance (outputs created by the wallet or "
2393  "confirmed outputs)"},
2394  {RPCResult::Type::STR_AMOUNT, "untrusted_pending",
2395  "untrusted pending balance (outputs created by "
2396  "others that are in the mempool)"},
2397  {RPCResult::Type::STR_AMOUNT, "immature",
2398  "balance from immature coinbase outputs"},
2399  {RPCResult::Type::STR_AMOUNT, "used",
2400  "(only present if avoid_reuse is set) balance from "
2401  "coins sent to addresses that were previously "
2402  "spent from (potentially privacy violating)"},
2403  }},
2405  "watchonly",
2406  "watchonly balances (not present if wallet does not "
2407  "watch anything)",
2408  {
2409  {RPCResult::Type::STR_AMOUNT, "trusted",
2410  "trusted balance (outputs created by the wallet or "
2411  "confirmed outputs)"},
2412  {RPCResult::Type::STR_AMOUNT, "untrusted_pending",
2413  "untrusted pending balance (outputs created by "
2414  "others that are in the mempool)"},
2415  {RPCResult::Type::STR_AMOUNT, "immature",
2416  "balance from immature coinbase outputs"},
2417  }},
2418  }},
2419  RPCExamples{HelpExampleCli("getbalances", "") +
2420  HelpExampleRpc("getbalances", "")},
2421  [&](const RPCHelpMan &self, const Config &config,
2422  const JSONRPCRequest &request) -> UniValue {
2423  std::shared_ptr<CWallet> const rpc_wallet =
2424  GetWalletForJSONRPCRequest(request);
2425  if (!rpc_wallet) {
2426  return NullUniValue;
2427  }
2428  CWallet &wallet = *rpc_wallet;
2429 
2430  // Make sure the results are valid at least up to the most recent
2431  // block the user could have gotten from another RPC command prior
2432  // to now
2433  wallet.BlockUntilSyncedToCurrentChain();
2434 
2435  LOCK(wallet.cs_wallet);
2436 
2437  const auto bal = GetBalance(wallet);
2438  UniValue balances{UniValue::VOBJ};
2439  {
2440  UniValue balances_mine{UniValue::VOBJ};
2441  balances_mine.pushKV("trusted", bal.m_mine_trusted);
2442  balances_mine.pushKV("untrusted_pending",
2443  bal.m_mine_untrusted_pending);
2444  balances_mine.pushKV("immature", bal.m_mine_immature);
2445  if (wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE)) {
2446  // If the AVOID_REUSE flag is set, bal has been set to just
2447  // the un-reused address balance. Get the total balance, and
2448  // then subtract bal to get the reused address balance.
2449  const auto full_bal = GetBalance(wallet, 0, false);
2450  balances_mine.pushKV("used",
2451  full_bal.m_mine_trusted +
2452  full_bal.m_mine_untrusted_pending -
2453  bal.m_mine_trusted -
2454  bal.m_mine_untrusted_pending);
2455  }
2456  balances.pushKV("mine", balances_mine);
2457  }
2458  auto spk_man = wallet.GetLegacyScriptPubKeyMan();
2459  if (spk_man && spk_man->HaveWatchOnly()) {
2460  UniValue balances_watchonly{UniValue::VOBJ};
2461  balances_watchonly.pushKV("trusted", bal.m_watchonly_trusted);
2462  balances_watchonly.pushKV("untrusted_pending",
2463  bal.m_watchonly_untrusted_pending);
2464  balances_watchonly.pushKV("immature", bal.m_watchonly_immature);
2465  balances.pushKV("watchonly", balances_watchonly);
2466  }
2467  return balances;
2468  },
2469  };
2470 }
2471 
2473  return RPCHelpMan{
2474  "getwalletinfo",
2475  "Returns an object containing various wallet state info.\n",
2476  {},
2477  RPCResult{
2479  "",
2480  "",
2481  {{
2482  {RPCResult::Type::STR, "walletname", "the wallet name"},
2483  {RPCResult::Type::NUM, "walletversion", "the wallet version"},
2484  {RPCResult::Type::STR_AMOUNT, "balance",
2485  "DEPRECATED. Identical to getbalances().mine.trusted"},
2486  {RPCResult::Type::STR_AMOUNT, "unconfirmed_balance",
2487  "DEPRECATED. Identical to "
2488  "getbalances().mine.untrusted_pending"},
2489  {RPCResult::Type::STR_AMOUNT, "immature_balance",
2490  "DEPRECATED. Identical to getbalances().mine.immature"},
2491  {RPCResult::Type::NUM, "txcount",
2492  "the total number of transactions in the wallet"},
2493  {RPCResult::Type::NUM_TIME, "keypoololdest",
2494  "the " + UNIX_EPOCH_TIME +
2495  " of the oldest pre-generated key in the key pool. "
2496  "Legacy wallets only."},
2497  {RPCResult::Type::NUM, "keypoolsize",
2498  "how many new keys are pre-generated (only counts external "
2499  "keys)"},
2500  {RPCResult::Type::NUM, "keypoolsize_hd_internal",
2501  "how many new keys are pre-generated for internal use (used "
2502  "for change outputs, only appears if the wallet is using "
2503  "this feature, otherwise external keys are used)"},
2504  {RPCResult::Type::NUM_TIME, "unlocked_until",
2505  /* optional */ true,
2506  "the " + UNIX_EPOCH_TIME +
2507  " until which the wallet is unlocked for transfers, or 0 "
2508  "if the wallet is locked (only present for "
2509  "passphrase-encrypted wallets)"},
2510  {RPCResult::Type::STR_AMOUNT, "paytxfee",
2511  "the transaction fee configuration, set in " +
2512  Currency::get().ticker + "/kB"},
2513  {RPCResult::Type::STR_HEX, "hdseedid", /* optional */ true,
2514  "the Hash160 of the HD seed (only present when HD is "
2515  "enabled)"},
2516  {RPCResult::Type::BOOL, "private_keys_enabled",
2517  "false if privatekeys are disabled for this wallet (enforced "
2518  "watch-only wallet)"},
2520  "scanning",
2521  "current scanning details, or false if no scan is in "
2522  "progress",
2523  {
2524  {RPCResult::Type::NUM, "duration",
2525  "elapsed seconds since scan start"},
2526  {RPCResult::Type::NUM, "progress",
2527  "scanning progress percentage [0.0, 1.0]"},
2528  },
2529  /*skip_type_check=*/true},
2530  {RPCResult::Type::BOOL, "avoid_reuse",
2531  "whether this wallet tracks clean/dirty coins in terms of "
2532  "reuse"},
2533  {RPCResult::Type::BOOL, "descriptors",
2534  "whether this wallet uses descriptors for scriptPubKey "
2535  "management"},
2536  }},
2537  },
2538  RPCExamples{HelpExampleCli("getwalletinfo", "") +
2539  HelpExampleRpc("getwalletinfo", "")},
2540  [&](const RPCHelpMan &self, const Config &config,
2541  const JSONRPCRequest &request) -> UniValue {
2542  std::shared_ptr<CWallet> const wallet =
2543  GetWalletForJSONRPCRequest(request);
2544  if (!wallet) {
2545  return NullUniValue;
2546  }
2547  const CWallet *const pwallet = wallet.get();
2548 
2549  // Make sure the results are valid at least up to the most recent
2550  // block the user could have gotten from another RPC command prior
2551  // to now
2552  pwallet->BlockUntilSyncedToCurrentChain();
2553 
2554  LOCK(pwallet->cs_wallet);
2555 
2556  UniValue obj(UniValue::VOBJ);
2557 
2558  size_t kpExternalSize = pwallet->KeypoolCountExternalKeys();
2559  const auto bal = GetBalance(*pwallet);
2560  int64_t kp_oldest = pwallet->GetOldestKeyPoolTime();
2561  obj.pushKV("walletname", pwallet->GetName());
2562  obj.pushKV("walletversion", pwallet->GetVersion());
2563  obj.pushKV("balance", bal.m_mine_trusted);
2564  obj.pushKV("unconfirmed_balance", bal.m_mine_untrusted_pending);
2565  obj.pushKV("immature_balance", bal.m_mine_immature);
2566  obj.pushKV("txcount", (int)pwallet->mapWallet.size());
2567  if (kp_oldest > 0) {
2568  obj.pushKV("keypoololdest", kp_oldest);
2569  }
2570  obj.pushKV("keypoolsize", (int64_t)kpExternalSize);
2571 
2572  LegacyScriptPubKeyMan *spk_man =
2573  pwallet->GetLegacyScriptPubKeyMan();
2574  if (spk_man) {
2575  CKeyID seed_id = spk_man->GetHDChain().seed_id;
2576  if (!seed_id.IsNull()) {
2577  obj.pushKV("hdseedid", seed_id.GetHex());
2578  }
2579  }
2580 
2581  if (pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) {
2582  obj.pushKV("keypoolsize_hd_internal",
2583  int64_t(pwallet->GetKeyPoolSize() - kpExternalSize));
2584  }
2585  if (pwallet->IsCrypted()) {
2586  obj.pushKV("unlocked_until", pwallet->nRelockTime);
2587  }
2588  obj.pushKV("paytxfee", pwallet->m_pay_tx_fee.GetFeePerK());
2589  obj.pushKV(
2590  "private_keys_enabled",
2592  if (pwallet->IsScanning()) {
2593  UniValue scanning(UniValue::VOBJ);
2594  scanning.pushKV("duration", pwallet->ScanningDuration() / 1000);
2595  scanning.pushKV("progress", pwallet->ScanningProgress());
2596  obj.pushKV("scanning", scanning);
2597  } else {
2598  obj.pushKV("scanning", false);
2599  }
2600  obj.pushKV("avoid_reuse",
2602  obj.pushKV("descriptors",
2604  return obj;
2605  },
2606  };
2607 }
2608 
2610  return RPCHelpMan{
2611  "listwalletdir",
2612  "Returns a list of wallets in the wallet directory.\n",
2613  {},
2614  RPCResult{
2616  "",
2617  "",
2618  {
2620  "wallets",
2621  "",
2622  {
2624  "",
2625  "",
2626  {
2627  {RPCResult::Type::STR, "name", "The wallet name"},
2628  }},
2629  }},
2630  }},
2631  RPCExamples{HelpExampleCli("listwalletdir", "") +
2632  HelpExampleRpc("listwalletdir", "")},
2633  [&](const RPCHelpMan &self, const Config &config,
2634  const JSONRPCRequest &request) -> UniValue {
2635  UniValue wallets(UniValue::VARR);
2636  for (const auto &path : ListWalletDir()) {
2638  wallet.pushKV("name", path.u8string());
2639  wallets.push_back(wallet);
2640  }
2641 
2642  UniValue result(UniValue::VOBJ);
2643  result.pushKV("wallets", wallets);
2644  return result;
2645  },
2646  };
2647 }
2648 
2650  return RPCHelpMan{
2651  "listwallets",
2652  "Returns a list of currently loaded wallets.\n"
2653  "For full information on the wallet, use \"getwalletinfo\"\n",
2654  {},
2656  "",
2657  "",
2658  {
2659  {RPCResult::Type::STR, "walletname", "the wallet name"},
2660  }},
2661  RPCExamples{HelpExampleCli("listwallets", "") +
2662  HelpExampleRpc("listwallets", "")},
2663  [&](const RPCHelpMan &self, const Config &config,
2664  const JSONRPCRequest &request) -> UniValue {
2665  UniValue obj(UniValue::VARR);
2666 
2667  for (const std::shared_ptr<CWallet> &wallet : GetWallets()) {
2668  LOCK(wallet->cs_wallet);
2669  obj.push_back(wallet->GetName());
2670  }
2671 
2672  return obj;
2673  },
2674  };
2675 }
2676 
2678  return RPCHelpMan{
2679  "loadwallet",
2680  "Loads a wallet from a wallet file or directory."
2681  "\nNote that all wallet command-line options used when starting "
2682  "bitcoind will be"
2683  "\napplied to the new wallet (eg -rescan, etc).\n",
2684  {
2686  "The wallet directory or .dat file."},
2687  {"load_on_startup", RPCArg::Type::BOOL,
2689  "Save wallet name to persistent settings and load on startup. "
2690  "True to add wallet to startup list, false to remove, null to "
2691  "leave unchanged."},
2692  },
2694  "",
2695  "",
2696  {
2697  {RPCResult::Type::STR, "name",
2698  "The wallet name if loaded successfully."},
2699  {RPCResult::Type::STR, "warning",
2700  "Warning message if wallet was not loaded cleanly."},
2701  }},
2702  RPCExamples{HelpExampleCli("loadwallet", "\"test.dat\"") +
2703  HelpExampleRpc("loadwallet", "\"test.dat\"")},
2704  [&](const RPCHelpMan &self, const Config &config,
2705  const JSONRPCRequest &request) -> UniValue {
2706  WalletContext &context = EnsureWalletContext(request.context);
2707  const std::string name(request.params[0].get_str());
2708 
2709  auto [wallet, warnings] =
2710  LoadWalletHelper(context, request.params[1], name);
2711 
2712  UniValue obj(UniValue::VOBJ);
2713  obj.pushKV("name", wallet->GetName());
2714  obj.pushKV("warning", Join(warnings, Untranslated("\n")).original);
2715 
2716  return obj;
2717  },
2718  };
2719 }
2720 
2722  std::string flags = "";
2723  for (auto &it : WALLET_FLAG_MAP) {
2724  if (it.second & MUTABLE_WALLET_FLAGS) {
2725  flags += (flags == "" ? "" : ", ") + it.first;
2726  }
2727  }
2728  return RPCHelpMan{
2729  "setwalletflag",
2730  "Change the state of the given wallet flag for a wallet.\n",
2731  {
2733  "The name of the flag to change. Current available flags: " +
2734  flags},
2735  {"value", RPCArg::Type::BOOL, RPCArg::Default{true},
2736  "The new state."},
2737  },
2739  "",
2740  "",
2741  {
2742  {RPCResult::Type::STR, "flag_name",
2743  "The name of the flag that was modified"},
2744  {RPCResult::Type::BOOL, "flag_state",
2745  "The new state of the flag"},
2746  {RPCResult::Type::STR, "warnings",
2747  "Any warnings associated with the change"},
2748  }},
2749  RPCExamples{HelpExampleCli("setwalletflag", "avoid_reuse") +
2750  HelpExampleRpc("setwalletflag", "\"avoid_reuse\"")},
2751  [&](const RPCHelpMan &self, const Config &config,
2752  const JSONRPCRequest &request) -> UniValue {
2753  std::shared_ptr<CWallet> const wallet =
2754  GetWalletForJSONRPCRequest(request);
2755  if (!wallet) {
2756  return NullUniValue;
2757  }
2758  CWallet *const pwallet = wallet.get();
2759 
2760  std::string flag_str = request.params[0].get_str();
2761  bool value =
2762  request.params[1].isNull() || request.params[1].get_bool();
2763 
2764  if (!WALLET_FLAG_MAP.count(flag_str)) {
2765  throw JSONRPCError(
2767  strprintf("Unknown wallet flag: %s", flag_str));
2768  }
2769 
2770  auto flag = WALLET_FLAG_MAP.at(flag_str);
2771 
2772  if (!(flag & MUTABLE_WALLET_FLAGS)) {
2773  throw JSONRPCError(
2775  strprintf("Wallet flag is immutable: %s", flag_str));
2776  }
2777 
2778  UniValue res(UniValue::VOBJ);
2779 
2780  if (pwallet->IsWalletFlagSet(flag) == value) {
2781  throw JSONRPCError(
2783  strprintf("Wallet flag is already set to %s: %s",
2784  value ? "true" : "false", flag_str));
2785  }
2786 
2787  res.pushKV("flag_name", flag_str);
2788  res.pushKV("flag_state", value);
2789 
2790  if (value) {
2791  pwallet->SetWalletFlag(flag);
2792  } else {
2793  pwallet->UnsetWalletFlag(flag);
2794  }
2795 
2796  if (flag && value && WALLET_FLAG_CAVEATS.count(flag)) {
2797  res.pushKV("warnings", WALLET_FLAG_CAVEATS.at(flag));
2798  }
2799 
2800  return res;
2801  },
2802  };
2803 }
2804 
2806  return RPCHelpMan{
2807  "createwallet",
2808  "Creates and loads a new wallet.\n",
2809  {
2810  {"wallet_name", RPCArg::Type::STR, RPCArg::Optional::NO,
2811  "The name for the new wallet. If this is a path, the wallet will "
2812  "be created at the path location."},
2813  {"disable_private_keys", RPCArg::Type::BOOL, RPCArg::Default{false},
2814  "Disable the possibility of private keys (only watchonlys are "
2815  "possible in this mode)."},
2816  {"blank", RPCArg::Type::BOOL, RPCArg::Default{false},
2817  "Create a blank wallet. A blank wallet has no keys or HD seed. "
2818  "One can be set using sethdseed."},
2820  "Encrypt the wallet with this passphrase."},
2821  {"avoid_reuse", RPCArg::Type::BOOL, RPCArg::Default{false},
2822  "Keep track of coin reuse, and treat dirty and clean coins "
2823  "differently with privacy considerations in mind."},
2824  {"descriptors", RPCArg::Type::BOOL, RPCArg::Default{false},
2825  "Create a native descriptor wallet. The wallet will use "
2826  "descriptors internally to handle address creation"},
2827  {"load_on_startup", RPCArg::Type::BOOL,
2829  "Save wallet name to persistent settings and load on startup. "
2830  "True to add wallet to startup list, false to remove, null to "
2831  "leave unchanged."},
2832  },
2834  "",
2835  "",
2836  {
2837  {RPCResult::Type::STR, "name",
2838  "The wallet name if created successfully. If the wallet "
2839  "was created using a full path, the wallet_name will be "
2840  "the full path."},
2841  {RPCResult::Type::STR, "warning",
2842  "Warning message if wallet was not loaded cleanly."},
2843  }},
2844  RPCExamples{
2845  HelpExampleCli("createwallet", "\"testwallet\"") +
2846  HelpExampleRpc("createwallet", "\"testwallet\"") +
2847  HelpExampleCliNamed("createwallet", {{"wallet_name", "descriptors"},
2848  {"avoid_reuse", true},
2849  {"descriptors", true},
2850  {"load_on_startup", true}}) +
2851  HelpExampleRpcNamed("createwallet", {{"wallet_name", "descriptors"},
2852  {"avoid_reuse", true},
2853  {"descriptors", true},
2854  {"load_on_startup", true}})},
2855  [&](const RPCHelpMan &self, const Config &config,
2856  const JSONRPCRequest &request) -> UniValue {
2857  WalletContext &context = EnsureWalletContext(request.context);
2858  uint64_t flags = 0;
2859  if (!request.params[1].isNull() && request.params[1].get_bool()) {
2861  }
2862 
2863  if (!request.params[2].isNull() && request.params[2].get_bool()) {
2865  }
2866 
2867  SecureString passphrase;
2868  passphrase.reserve(100);
2869  std::vector<bilingual_str> warnings;
2870  if (!request.params[3].isNull()) {
2871  passphrase = request.params[3].get_str().c_str();
2872  if (passphrase.empty()) {
2873  // Empty string means unencrypted
2874  warnings.emplace_back(Untranslated(
2875  "Empty string given as passphrase, wallet will "
2876  "not be encrypted."));
2877  }
2878  }
2879 
2880  if (!request.params[4].isNull() && request.params[4].get_bool()) {
2882  }
2883  if (!request.params[5].isNull() && request.params[5].get_bool()) {
2885  warnings.emplace_back(Untranslated(
2886  "Wallet is an experimental descriptor wallet"));
2887  }
2888 
2889  DatabaseOptions options;
2890  DatabaseStatus status;
2891  options.require_create = true;
2892  options.create_flags = flags;
2893  options.create_passphrase = passphrase;
2895  std::optional<bool> load_on_start =
2896  request.params[6].isNull()
2897  ? std::nullopt
2898  : std::make_optional<bool>(request.params[6].get_bool());
2899  std::shared_ptr<CWallet> wallet =
2900  CreateWallet(*context.chain, request.params[0].get_str(),
2901  load_on_start, options, status, error, warnings);
2902  if (!wallet) {
2905  : RPC_WALLET_ERROR;
2906  throw JSONRPCError(code, error.original);
2907  }
2908 
2909  UniValue obj(UniValue::VOBJ);
2910  obj.pushKV("name", wallet->GetName());
2911  obj.pushKV("warning", Join(warnings, Untranslated("\n")).original);
2912 
2913  return obj;
2914  },
2915  };
2916 }
2917 
2919  return RPCHelpMan{
2920  "unloadwallet",
2921  "Unloads the wallet referenced by the request endpoint otherwise "
2922  "unloads the wallet specified in the argument.\n"
2923  "Specifying the wallet name on a wallet endpoint is invalid.",
2924  {
2925  {"wallet_name", RPCArg::Type::STR,
2926  RPCArg::DefaultHint{"the wallet name from the RPC request"},
2927  "The name of the wallet to unload."},
2928  {"load_on_startup", RPCArg::Type::BOOL,
2930  "Save wallet name to persistent settings and load on startup. "
2931  "True to add wallet to startup list, false to remove, null to "
2932  "leave unchanged."},
2933  },
2935  "",
2936  "",
2937  {
2938  {RPCResult::Type::STR, "warning",
2939  "Warning message if wallet was not unloaded cleanly."},
2940  }},
2941  RPCExamples{HelpExampleCli("unloadwallet", "wallet_name") +
2942  HelpExampleRpc("unloadwallet", "wallet_name")},
2943  [&](const RPCHelpMan &self, const Config &config,
2944  const JSONRPCRequest &request) -> UniValue {
2945  std::string wallet_name;
2946  if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
2947  if (!request.params[0].isNull()) {
2949  "Cannot unload the requested wallet");
2950  }
2951  } else {
2952  wallet_name = request.params[0].get_str();
2953  }
2954 
2955  std::shared_ptr<CWallet> wallet = GetWallet(wallet_name);
2956  if (!wallet) {
2957  throw JSONRPCError(
2959  "Requested wallet does not exist or is not loaded");
2960  }
2961 
2962  // Release the "main" shared pointer and prevent further
2963  // notifications. Note that any attempt to load the same wallet
2964  // would fail until the wallet is destroyed (see CheckUniqueFileid).
2965  std::vector<bilingual_str> warnings;
2966  std::optional<bool> load_on_start =
2967  request.params[1].isNull()
2968  ? std::nullopt
2969  : std::make_optional<bool>(request.params[1].get_bool());
2970  if (!RemoveWallet(wallet, load_on_start, warnings)) {
2972  "Requested wallet already unloaded");
2973  }
2974 
2975  UnloadWallet(std::move(wallet));
2976 
2977  UniValue result(UniValue::VOBJ);
2978  result.pushKV("warning",
2979  Join(warnings, Untranslated("\n")).original);
2980  return result;
2981  },
2982  };
2983 }
2984 
2986  const auto &ticker = Currency::get().ticker;
2987  return RPCHelpMan{
2988  "listunspent",
2989  "Returns array of unspent transaction outputs\n"
2990  "with between minconf and maxconf (inclusive) confirmations.\n"
2991  "Optionally filter to only include txouts paid to specified "
2992  "addresses.\n",
2993  {
2994  {"minconf", RPCArg::Type::NUM, RPCArg::Default{1},
2995  "The minimum confirmations to filter"},
2996  {"maxconf", RPCArg::Type::NUM, RPCArg::Default{9999999},
2997  "The maximum confirmations to filter"},
2998  {
2999  "addresses",
3002  "The bitcoin addresses to filter",
3003  {
3005  "bitcoin address"},
3006  },
3007  },
3008  {"include_unsafe", RPCArg::Type::BOOL, RPCArg::Default{true},
3009  "Include outputs that are not safe to spend\n"
3010  " See description of \"safe\" attribute below."},
3011  {"query_options",
3014  "JSON with query options",
3015  {
3016  {"minimumAmount", RPCArg::Type::AMOUNT,
3018  "Minimum value of each UTXO in " + ticker + ""},
3019  {"maximumAmount", RPCArg::Type::AMOUNT,
3020  RPCArg::DefaultHint{"unlimited"},
3021  "Maximum value of each UTXO in " + ticker + ""},
3022  {"maximumCount", RPCArg::Type::NUM,
3023  RPCArg::DefaultHint{"unlimited"}, "Maximum number of UTXOs"},
3024  {"minimumSumAmount", RPCArg::Type::AMOUNT,
3025  RPCArg::DefaultHint{"unlimited"},
3026  "Minimum sum value of all UTXOs in " + ticker + ""},
3027  },
3028  RPCArgOptions{.oneline_description = "query_options"}},
3029  },
3030  RPCResult{
3032  "",
3033  "",
3034  {
3036  "",
3037  "",
3038  {
3039  {RPCResult::Type::STR_HEX, "txid", "the transaction id"},
3040  {RPCResult::Type::NUM, "vout", "the vout value"},
3041  {RPCResult::Type::STR, "address", "the bitcoin address"},
3042  {RPCResult::Type::STR, "label",
3043  "The associated label, or \"\" for the default label"},
3044  {RPCResult::Type::STR, "scriptPubKey", "the script key"},
3045  {RPCResult::Type::STR_AMOUNT, "amount",
3046  "the transaction output amount in " + ticker},
3047  {RPCResult::Type::NUM, "confirmations",
3048  "The number of confirmations"},
3049  {RPCResult::Type::NUM, "ancestorcount",
3050  /* optional */ true,
3051  "DEPRECATED: The number of in-mempool ancestor "
3052  "transactions, including this one (if transaction is in "
3053  "the mempool). Only displayed if the "
3054  "-deprecatedrpc=mempool_ancestors_descendants option is "
3055  "set"},
3056  {RPCResult::Type::NUM, "ancestorsize", /* optional */ true,
3057  "DEPRECATED: The virtual transaction size of in-mempool "
3058  " ancestors, including this one (if transaction is in "
3059  "the mempool). Only displayed if the "
3060  "-deprecatedrpc=mempool_ancestors_descendants option is "
3061  "set"},
3062  {RPCResult::Type::STR_AMOUNT, "ancestorfees",
3063  /* optional */ true,
3064  "DEPRECATED: The total fees of in-mempool ancestors "
3065  "(including this one) with fee deltas used for mining "
3066  "priority in " +
3067  ticker +
3068  " (if transaction is in the mempool). Only "
3069  "displayed if the "
3070  "-deprecatedrpc=mempool_ancestors_descendants option "
3071  "is "
3072  "set"},
3073  {RPCResult::Type::STR_HEX, "redeemScript",
3074  "The redeemScript if scriptPubKey is P2SH"},
3075  {RPCResult::Type::BOOL, "spendable",
3076  "Whether we have the private keys to spend this output"},
3077  {RPCResult::Type::BOOL, "solvable",
3078  "Whether we know how to spend this output, ignoring the "
3079  "lack of keys"},
3080  {RPCResult::Type::BOOL, "reused",
3081  "(only present if avoid_reuse is set) Whether this "
3082  "output is reused/dirty (sent to an address that was "
3083  "previously spent from)"},
3084  {RPCResult::Type::STR, "desc",
3085  "(only when solvable) A descriptor for spending this "
3086  "output"},
3087  {RPCResult::Type::BOOL, "safe",
3088  "Whether this output is considered safe to spend. "
3089  "Unconfirmed transactions\n"
3090  "from outside keys are considered unsafe\n"
3091  "and are not eligible for spending by fundrawtransaction "
3092  "and sendtoaddress."},
3093  }},
3094  }},
3095  RPCExamples{
3096  HelpExampleCli("listunspent", "") +
3097  HelpExampleCli("listunspent",
3098  "6 9999999 "
3099  "\"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\","
3100  "\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"") +
3101  HelpExampleRpc("listunspent",
3102  "6, 9999999 "
3103  "\"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\","
3104  "\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"") +
3106  "listunspent",
3107  "6 9999999 '[]' true '{ \"minimumAmount\": 0.005 }'") +
3109  "listunspent",
3110  "6, 9999999, [] , true, { \"minimumAmount\": 0.005 } ")},
3111  [&](const RPCHelpMan &self, const Config &config,
3112  const JSONRPCRequest &request) -> UniValue {
3113  std::shared_ptr<CWallet> const wallet =
3114  GetWalletForJSONRPCRequest(request);
3115  if (!wallet) {
3116  return NullUniValue;
3117  }
3118  const CWallet *const pwallet = wallet.get();
3119 
3120  int nMinDepth = 1;
3121  if (!request.params[0].isNull()) {
3122  RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
3123  nMinDepth = request.params[0].get_int();
3124  }
3125 
3126  int nMaxDepth = 9999999;
3127  if (!request.params[1].isNull()) {
3128  RPCTypeCheckArgument(request.params[1], UniValue::VNUM);
3129  nMaxDepth = request.params[1].get_int();
3130  }
3131 
3132  std::set<CTxDestination> destinations;
3133  if (!request.params[2].isNull()) {
3134  RPCTypeCheckArgument(request.params[2], UniValue::VARR);
3135  UniValue inputs = request.params[2].get_array();
3136  for (size_t idx = 0; idx < inputs.size(); idx++) {
3137  const UniValue &input = inputs[idx];
3139  input.get_str(), wallet->GetChainParams());
3140  if (!IsValidDestination(dest)) {
3141  throw JSONRPCError(
3143  std::string("Invalid Bitcoin address: ") +
3144  input.get_str());
3145  }
3146  if (!destinations.insert(dest).second) {
3147  throw JSONRPCError(
3149  std::string(
3150  "Invalid parameter, duplicated address: ") +
3151  input.get_str());
3152  }
3153  }
3154  }
3155 
3156  bool include_unsafe = true;
3157  if (!request.params[3].isNull()) {
3158  RPCTypeCheckArgument(request.params[3], UniValue::VBOOL);
3159  include_unsafe = request.params[3].get_bool();
3160  }
3161 
3162  Amount nMinimumAmount = Amount::zero();
3163  Amount nMaximumAmount = MAX_MONEY;
3164  Amount nMinimumSumAmount = MAX_MONEY;
3165  uint64_t nMaximumCount = 0;
3166 
3167  if (!request.params[4].isNull()) {
3168  const UniValue &options = request.params[4].get_obj();
3169 
3171  options,
3172  {
3173  {"minimumAmount", UniValueType()},
3174  {"maximumAmount", UniValueType()},
3175  {"minimumSumAmount", UniValueType()},
3176  {"maximumCount", UniValueType(UniValue::VNUM)},
3177  },
3178  true, true);
3179 
3180  if (options.exists("minimumAmount")) {
3181  nMinimumAmount = AmountFromValue(options["minimumAmount"]);
3182  }
3183 
3184  if (options.exists("maximumAmount")) {
3185  nMaximumAmount = AmountFromValue(options["maximumAmount"]);
3186  }
3187 
3188  if (options.exists("minimumSumAmount")) {
3189  nMinimumSumAmount =
3190  AmountFromValue(options["minimumSumAmount"]);
3191  }
3192 
3193  if (options.exists("maximumCount")) {
3194  nMaximumCount = options["maximumCount"].get_int64();
3195  }
3196  }
3197 
3198  // Make sure the results are valid at least up to the most recent
3199  // block the user could have gotten from another RPC command prior
3200  // to now
3201  pwallet->BlockUntilSyncedToCurrentChain();
3202 
3203  UniValue results(UniValue::VARR);
3204  std::vector<COutput> vecOutputs;
3205  {
3206  CCoinControl cctl;
3207  cctl.m_avoid_address_reuse = false;
3208  cctl.m_min_depth = nMinDepth;
3209  cctl.m_max_depth = nMaxDepth;
3210  cctl.m_include_unsafe_inputs = include_unsafe;
3211  LOCK(pwallet->cs_wallet);
3212  AvailableCoins(*pwallet, vecOutputs, &cctl, nMinimumAmount,
3213  nMaximumAmount, nMinimumSumAmount,
3214  nMaximumCount);
3215  }
3216 
3217  LOCK(pwallet->cs_wallet);
3218 
3219  const bool avoid_reuse =
3221 
3222  for (const COutput &out : vecOutputs) {
3223  CTxDestination address;
3224  const CScript &scriptPubKey =
3225  out.tx->tx->vout[out.i].scriptPubKey;
3226  bool fValidAddress = ExtractDestination(scriptPubKey, address);
3227  bool reused =
3228  avoid_reuse && pwallet->IsSpentKey(out.tx->GetId(), out.i);
3229 
3230  if (destinations.size() &&
3231  (!fValidAddress || !destinations.count(address))) {
3232  continue;
3233  }
3234 
3235  UniValue entry(UniValue::VOBJ);
3236  entry.pushKV("txid", out.tx->GetId().GetHex());
3237  entry.pushKV("vout", out.i);
3238 
3239  if (fValidAddress) {
3240  entry.pushKV("address", EncodeDestination(address, config));
3241 
3242  const auto *address_book_entry =
3243  pwallet->FindAddressBookEntry(address);
3244  if (address_book_entry) {
3245  entry.pushKV("label", address_book_entry->GetLabel());
3246  }
3247 
3248  std::unique_ptr<SigningProvider> provider =
3249  pwallet->GetSolvingProvider(scriptPubKey);
3250  if (provider) {
3251  if (scriptPubKey.IsPayToScriptHash()) {
3252  const CScriptID &hash =
3253  CScriptID(std::get<ScriptHash>(address));
3254  CScript redeemScript;
3255  if (provider->GetCScript(hash, redeemScript)) {
3256  entry.pushKV("redeemScript",
3257  HexStr(redeemScript));
3258  }
3259  }
3260  }
3261  }
3262 
3263  entry.pushKV("scriptPubKey", HexStr(scriptPubKey));
3264  entry.pushKV("amount", out.tx->tx->vout[out.i].nValue);
3265  entry.pushKV("confirmations", out.nDepth);
3266  entry.pushKV("spendable", out.fSpendable);
3267  entry.pushKV("solvable", out.fSolvable);
3268  if (out.fSolvable) {
3269  std::unique_ptr<SigningProvider> provider =
3270  pwallet->GetSolvingProvider(scriptPubKey);
3271  if (provider) {
3272  auto descriptor =
3273  InferDescriptor(scriptPubKey, *provider);
3274  entry.pushKV("desc", descriptor->ToString());
3275  }
3276  }
3277  if (avoid_reuse) {
3278  entry.pushKV("reused", reused);
3279  }
3280  entry.pushKV("safe", out.fSafe);
3281  results.push_back(entry);
3282  }
3283 
3284  return results;
3285  },
3286  };
3287 }
3288 
3290  Amount &fee_out, int &change_position,
3291  const UniValue &options, CCoinControl &coinControl) {
3292  // Make sure the results are valid at least up to the most recent block
3293  // the user could have gotten from another RPC command prior to now
3294  pwallet->BlockUntilSyncedToCurrentChain();
3295 
3296  change_position = -1;
3297  bool lockUnspents = false;
3298  UniValue subtractFeeFromOutputs;
3299  std::set<int> setSubtractFeeFromOutputs;
3300 
3301  if (!options.isNull()) {
3302  if (options.type() == UniValue::VBOOL) {
3303  // backward compatibility bool only fallback
3304  coinControl.fAllowWatchOnly = options.get_bool();
3305  } else {
3308  options,
3309  {
3310  {"add_inputs", UniValueType(UniValue::VBOOL)},
3311  {"include_unsafe", UniValueType(UniValue::VBOOL)},
3312  {"add_to_wallet", UniValueType(UniValue::VBOOL)},
3313  {"changeAddress", UniValueType(UniValue::VSTR)},
3314  {"change_address", UniValueType(UniValue::VSTR)},
3315  {"changePosition", UniValueType(UniValue::VNUM)},
3316  {"change_position", UniValueType(UniValue::VNUM)},
3317  {"includeWatching", UniValueType(UniValue::VBOOL)},
3318  {"include_watching", UniValueType(UniValue::VBOOL)},
3319  {"inputs", UniValueType(UniValue::VARR)},
3320  {"lockUnspents", UniValueType(UniValue::VBOOL)},
3321  {"lock_unspents", UniValueType(UniValue::VBOOL)},
3322  {"locktime", UniValueType(UniValue::VNUM)},
3323  // will be checked below
3324  {"feeRate", UniValueType()},
3325  {"fee_rate", UniValueType()},
3326  {"psbt", UniValueType(UniValue::VBOOL)},
3327  {"subtractFeeFromOutputs", UniValueType(UniValue::VARR)},
3328  {"subtract_fee_from_outputs", UniValueType(UniValue::VARR)},
3329  },
3330  true, true);
3331 
3332  if (options.exists("add_inputs")) {
3333  coinControl.m_add_inputs = options["add_inputs"].get_bool();
3334  }
3335 
3336  if (options.exists("changeAddress") ||
3337  options.exists("change_address")) {
3338  const std::string change_address_str =
3339  (options.exists("change_address")
3340  ? options["change_address"]
3341  : options["changeAddress"])
3342  .get_str();
3344  change_address_str, pwallet->GetChainParams());
3345 
3346  if (!IsValidDestination(dest)) {
3347  throw JSONRPCError(
3349  "Change address must be a valid bitcoin address");
3350  }
3351 
3352  coinControl.destChange = dest;
3353  }
3354 
3355  if (options.exists("changePosition") ||
3356  options.exists("change_position")) {
3357  change_position = (options.exists("change_position")
3358  ? options["change_position"]
3359  : options["changePosition"])
3360  .get_int();
3361  }
3362 
3363  const UniValue include_watching_option =
3364  options.exists("include_watching") ? options["include_watching"]
3365  : options["includeWatching"];
3366  coinControl.fAllowWatchOnly =
3367  ParseIncludeWatchonly(include_watching_option, *pwallet);
3368 
3369  if (options.exists("lockUnspents") ||
3370  options.exists("lock_unspents")) {
3371  lockUnspents =
3372  (options.exists("lock_unspents") ? options["lock_unspents"]
3373  : options["lockUnspents"])
3374  .get_bool();
3375  }
3376 
3377  if (options.exists("include_unsafe")) {
3378  coinControl.m_include_unsafe_inputs =
3379  options["include_unsafe"].get_bool();
3380  }
3381 
3382  if (options.exists("feeRate") || options.exists("fee_rate")) {
3383  coinControl.m_feerate = CFeeRate(AmountFromValue(
3384  options.exists("fee_rate") ? options["fee_rate"]
3385  : options["feeRate"]));
3386  coinControl.fOverrideFeeRate = true;
3387  }
3388 
3389  if (options.exists("subtractFeeFromOutputs") ||
3390  options.exists("subtract_fee_from_outputs")) {
3391  subtractFeeFromOutputs =
3392  (options.exists("subtract_fee_from_outputs")
3393  ? options["subtract_fee_from_outputs"]
3394  : options["subtractFeeFromOutputs"])
3395  .get_array();
3396  }
3397  }
3398  } else {
3399  // if options is null and not a bool
3400  coinControl.fAllowWatchOnly =
3402  }
3403 
3404  if (tx.vout.size() == 0) {
3406  "TX must have at least one output");
3407  }
3408 
3409  if (change_position != -1 &&
3410  (change_position < 0 ||
3411  (unsigned int)change_position > tx.vout.size())) {
3413  "changePosition out of bounds");
3414  }
3415 
3416  for (size_t idx = 0; idx < subtractFeeFromOutputs.size(); idx++) {
3417  int pos = subtractFeeFromOutputs[idx].get_int();
3418  if (setSubtractFeeFromOutputs.count(pos)) {
3419  throw JSONRPCError(
3421  strprintf("Invalid parameter, duplicated position: %d", pos));
3422  }
3423  if (pos < 0) {
3424  throw JSONRPCError(
3426  strprintf("Invalid parameter, negative position: %d", pos));
3427  }
3428  if (pos >= int(tx.vout.size())) {
3429  throw JSONRPCError(
3431  strprintf("Invalid parameter, position too large: %d", pos));
3432  }
3433  setSubtractFeeFromOutputs.insert(pos);
3434  }
3435 
3437 
3438  if (!FundTransaction(*pwallet, tx, fee_out, change_position, error,
3439  lockUnspents, setSubtractFeeFromOutputs,
3440  coinControl)) {
3441  throw JSONRPCError(RPC_WALLET_ERROR, error.original);
3442  }
3443 }
3444 
3446  const auto &ticker = Currency::get().ticker;
3447  return RPCHelpMan{
3448  "fundrawtransaction",
3449  "If the transaction has no inputs, they will be automatically selected "
3450  "to meet its out value.\n"
3451  "It will add at most one change output to the outputs.\n"
3452  "No existing outputs will be modified unless "
3453  "\"subtractFeeFromOutputs\" is specified.\n"
3454  "Note that inputs which were signed may need to be resigned after "
3455  "completion since in/outputs have been added.\n"
3456  "The inputs added will not be signed, use signrawtransactionwithkey or "
3457  "signrawtransactionwithwallet for that.\n"
3458  "Note that all existing inputs must have their previous output "
3459  "transaction be in the wallet.\n"
3460  "Note that all inputs selected must be of standard form and P2SH "
3461  "scripts must be\n"
3462  "in the wallet using importaddress or addmultisigaddress (to calculate "
3463  "fees).\n"
3464  "You can see whether this is the case by checking the \"solvable\" "
3465  "field in the listunspent output.\n"
3466  "Only pay-to-pubkey, multisig, and P2SH versions thereof are currently "
3467  "supported for watch-only\n",
3468  {
3470  "The hex string of the raw transaction"},
3471  {"options",
3474  "for backward compatibility: passing in a true instead of an "
3475  "object will result in {\"includeWatching\":true}",
3476  {
3477  {"add_inputs", RPCArg::Type::BOOL, RPCArg::Default{true},
3478  "For a transaction with existing inputs, automatically "
3479  "include more if they are not enough."},
3480  {"include_unsafe", RPCArg::Type::BOOL, RPCArg::Default{false},
3481  "Include inputs that are not safe to spend (unconfirmed "
3482  "transactions from outside keys).\n"
3483  "Warning: the resulting transaction may become invalid if "
3484  "one of the unsafe inputs disappears.\n"
3485  "If that happens, you will need to fund the transaction with "
3486  "different inputs and republish it."},
3487  {"changeAddress", RPCArg::Type::STR,
3488  RPCArg::DefaultHint{"pool address"},
3489  "The bitcoin address to receive the change"},
3490  {"changePosition", RPCArg::Type::NUM,
3491  RPCArg::DefaultHint{"random"},
3492  "The index of the change output"},
3493  {"includeWatching", RPCArg::Type::BOOL,
3495  "true for watch-only wallets, otherwise false"},
3496  "Also select inputs which are watch only.\n"
3497  "Only solvable inputs can be used. Watch-only destinations "
3498  "are solvable if the public key and/or output script was "
3499  "imported,\n"
3500  "e.g. with 'importpubkey' or 'importmulti' with the "
3501  "'pubkeys' or 'desc' field."},
3502  {"lockUnspents", RPCArg::Type::BOOL, RPCArg::Default{false},
3503  "Lock selected unspent outputs"},
3504  {"feeRate", RPCArg::Type::AMOUNT,
3506  "not set: makes wallet determine the fee"},
3507  "Set a specific fee rate in " + ticker + "/kB"},
3508  {
3509  "subtractFeeFromOutputs",
3512  "The integers.\n"
3513  " The fee will be equally "
3514  "deducted from the amount of each specified output.\n"
3515  " Those recipients will "
3516  "receive less bitcoins than you enter in their "
3517  "corresponding amount field.\n"
3518  " If no outputs are "
3519  "specified here, the sender pays the fee.",
3520  {
3521  {"vout_index", RPCArg::Type::NUM,
3523  "The zero-based output index, before a change output "
3524  "is added."},
3525  },
3526  },
3527  },
3529  .oneline_description = "options"}},
3530  },
3532  "",
3533  "",
3534  {
3535  {RPCResult::Type::STR_HEX, "hex",
3536  "The resulting raw transaction (hex-encoded string)"},
3538  "Fee in " + ticker + " the resulting transaction pays"},
3539  {RPCResult::Type::NUM, "changepos",
3540  "The position of the added change output, or -1"},
3541  }},
3542  RPCExamples{
3543  "\nCreate a transaction with no inputs\n" +
3544  HelpExampleCli("createrawtransaction",
3545  "\"[]\" \"{\\\"myaddress\\\":10000}\"") +
3546  "\nAdd sufficient unsigned inputs to meet the output value\n" +
3547  HelpExampleCli("fundrawtransaction", "\"rawtransactionhex\"") +
3548  "\nSign the transaction\n" +
3549  HelpExampleCli("signrawtransactionwithwallet",
3550  "\"fundedtransactionhex\"") +
3551  "\nSend the transaction\n" +
3552  HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")},
3553  [&](const RPCHelpMan &self, const Config &config,
3554  const JSONRPCRequest &request) -> UniValue {
3555  std::shared_ptr<CWallet> const wallet =
3556  GetWalletForJSONRPCRequest(request);
3557  if (!wallet) {
3558  return NullUniValue;
3559  }
3560  CWallet *const pwallet = wallet.get();
3561 
3562  // parse hex string from parameter
3564  if (!DecodeHexTx(tx, request.params[0].get_str())) {
3566  "TX decode failed");
3567  }
3568 
3569  Amount fee;
3570  int change_position;
3571  CCoinControl coin_control;
3572  // Automatically select (additional) coins. Can be overridden by
3573  // options.add_inputs.
3574  coin_control.m_add_inputs = true;
3575  FundTransaction(pwallet, tx, fee, change_position,
3576  request.params[1], coin_control);
3577 
3578  UniValue result(UniValue::VOBJ);
3579  result.pushKV("hex", EncodeHexTx(CTransaction(tx)));
3580  result.pushKV("fee", fee);
3581  result.pushKV("changepos", change_position);
3582 
3583  return result;
3584  },
3585  };
3586 }
3587 
3589  return RPCHelpMan{
3590  "signrawtransactionwithwallet",
3591  "Sign inputs for raw transaction (serialized, hex-encoded).\n"
3592  "The second optional argument (may be null) is an array of previous "
3593  "transaction outputs that\n"
3594  "this transaction depends on but may not yet be in the block chain.\n" +
3596  {
3597  {"hexstring", RPCArg::Type::STR, RPCArg::Optional::NO,
3598  "The transaction hex string"},
3599  {
3600  "prevtxs",
3603  "The previous dependent transaction outputs",
3604  {
3605  {
3606  "",
3609  "",
3610  {
3611  {"txid", RPCArg::Type::STR_HEX,
3612  RPCArg::Optional::NO, "The transaction id"},
3614  "The output number"},
3615  {"scriptPubKey", RPCArg::Type::STR_HEX,
3616  RPCArg::Optional::NO, "script key"},
3617  {"redeemScript", RPCArg::Type::STR_HEX,
3618  RPCArg::Optional::OMITTED, "(required for P2SH)"},
3619  {"amount", RPCArg::Type::AMOUNT,
3620  RPCArg::Optional::NO, "The amount spent"},
3621  },
3622  },
3623  },
3624  },
3625  {"sighashtype", RPCArg::Type::STR, RPCArg::Default{"ALL|FORKID"},
3626  "The signature hash type. Must be one of\n"
3627  " \"ALL|FORKID\"\n"
3628  " \"NONE|FORKID\"\n"
3629  " \"SINGLE|FORKID\"\n"
3630  " \"ALL|FORKID|ANYONECANPAY\"\n"
3631  " \"NONE|FORKID|ANYONECANPAY\"\n"
3632  " \"SINGLE|FORKID|ANYONECANPAY\""},
3633  },
3634  RPCResult{
3636  "",
3637  "",
3638  {
3639  {RPCResult::Type::STR_HEX, "hex",
3640  "The hex-encoded raw transaction with signature(s)"},
3641  {RPCResult::Type::BOOL, "complete",
3642  "If the transaction has a complete set of signatures"},
3644  "errors",
3645  /* optional */ true,
3646  "Script verification errors (if there are any)",
3647  {
3649  "",
3650  "",
3651  {
3652  {RPCResult::Type::STR_HEX, "txid",
3653  "The hash of the referenced, previous transaction"},
3654  {RPCResult::Type::NUM, "vout",
3655  "The index of the output to spent and used as "
3656  "input"},
3657  {RPCResult::Type::STR_HEX, "scriptSig",
3658  "The hex-encoded signature script"},
3659  {RPCResult::Type::NUM, "sequence",
3660  "Script sequence number"},
3661  {RPCResult::Type::STR, "error",
3662  "Verification or signing error related to the "
3663  "input"},
3664  }},
3665  }},
3666  }},
3667  RPCExamples{
3668  HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") +
3669  HelpExampleRpc("signrawtransactionwithwallet", "\"myhex\"")},
3670  [&](const RPCHelpMan &self, const Config &config,
3671  const JSONRPCRequest &request) -> UniValue {
3672  std::shared_ptr<CWallet> const wallet =
3673  GetWalletForJSONRPCRequest(request);
3674  if (!wallet) {
3675  return NullUniValue;
3676  }
3677  const CWallet *const pwallet = wallet.get();
3678 
3679  CMutableTransaction mtx;
3680  if (!DecodeHexTx(mtx, request.params[0].get_str())) {
3682  "TX decode failed");
3683  }
3684 
3685  // Sign the transaction
3686  LOCK(pwallet->cs_wallet);
3687  EnsureWalletIsUnlocked(pwallet);
3688 
3689  // Fetch previous transactions (inputs):
3690  std::map<COutPoint, Coin> coins;
3691  for (const CTxIn &txin : mtx.vin) {
3692  // Create empty map entry keyed by prevout.
3693  coins[txin.prevout];
3694  }
3695  pwallet->chain().findCoins(coins);
3696 
3697  // Parse the prevtxs array
3698  ParsePrevouts(request.params[1], nullptr, coins);
3699 
3700  SigHashType nHashType = ParseSighashString(request.params[2]);
3701  if (!nHashType.hasForkId()) {
3703  "Signature must use SIGHASH_FORKID");
3704  }
3705 
3706  // Script verification errors
3707  std::map<int, std::string> input_errors;
3708 
3709  bool complete =
3710  pwallet->SignTransaction(mtx, coins, nHashType, input_errors);
3711  UniValue result(UniValue::VOBJ);
3712  SignTransactionResultToJSON(mtx, complete, coins, input_errors,
3713  result);
3714  return result;
3715  },
3716  };
3717 }
3718 
3720  return RPCHelpMan{
3721  "rescanblockchain",
3722  "Rescan the local blockchain for wallet related transactions.\n"
3723  "Note: Use \"getwalletinfo\" to query the scanning progress.\n",
3724  {
3725  {"start_height", RPCArg::Type::NUM, RPCArg::Default{0},
3726  "block height where the rescan should start"},
3727  {"stop_height", RPCArg::Type::NUM,
3729  "the last block height that should be scanned"},
3730  },
3731  RPCResult{
3733  "",
3734  "",
3735  {
3736  {RPCResult::Type::NUM, "start_height",
3737  "The block height where the rescan started (the requested "
3738  "height or 0)"},
3739  {RPCResult::Type::NUM, "stop_height",
3740  "The height of the last rescanned block. May be null in rare "
3741  "cases if there was a reorg and the call didn't scan any "
3742  "blocks because they were already scanned in the background."},
3743  }},
3744  RPCExamples{HelpExampleCli("rescanblockchain", "100000 120000") +
3745  HelpExampleRpc("rescanblockchain", "100000, 120000")},
3746  [&](const RPCHelpMan &self, const Config &config,
3747  const JSONRPCRequest &request) -> UniValue {
3748  std::shared_ptr<CWallet> const wallet =
3749  GetWalletForJSONRPCRequest(request);
3750  if (!wallet) {
3751  return NullUniValue;
3752  }
3753  CWallet *const pwallet = wallet.get();
3754 
3755  WalletRescanReserver reserver(*pwallet);
3756  if (!reserver.reserve()) {
3758  "Wallet is currently rescanning. Abort "
3759  "existing rescan or wait.");
3760  }
3761 
3762  int start_height = 0;
3763  std::optional<int> stop_height;
3764  BlockHash start_block;
3765  {
3766  LOCK(pwallet->cs_wallet);
3767  int tip_height = pwallet->GetLastBlockHeight();
3768 
3769  if (!request.params[0].isNull()) {
3770  start_height = request.params[0].get_int();
3771  if (start_height < 0 || start_height > tip_height) {
3773  "Invalid start_height");
3774  }
3775  }
3776 
3777  if (!request.params[1].isNull()) {
3778  stop_height = request.params[1].get_int();
3779  if (*stop_height < 0 || *stop_height > tip_height) {
3781  "Invalid stop_height");
3782  } else if (*stop_height < start_height) {
3783  throw JSONRPCError(
3785  "stop_height must be greater than start_height");
3786  }
3787  }
3788 
3789  // We can't rescan beyond non-pruned blocks, stop and throw an
3790  // error
3791  if (!pwallet->chain().hasBlocks(pwallet->GetLastBlockHash(),
3792  start_height, stop_height)) {
3793  throw JSONRPCError(
3795  "Can't rescan beyond pruned data. Use RPC call "
3796  "getblockchaininfo to determine your pruned height.");
3797  }
3798 
3800  pwallet->GetLastBlockHash(), start_height,
3801  FoundBlock().hash(start_block)));
3802  }
3803 
3805  start_block, start_height, stop_height, reserver,
3806  true /* fUpdate */);
3807  switch (result.status) {
3809  break;
3811  throw JSONRPCError(
3813  "Rescan failed. Potentially corrupted data files.");
3815  throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted.");
3816  // no default case, so the compiler can warn about missing
3817  // cases
3818  }
3820  response.pushKV("start_height", start_height);
3821  response.pushKV("stop_height", result.last_scanned_height
3822  ? *result.last_scanned_height
3823  : UniValue());
3824  return response;
3825  },
3826  };
3827 }
3828 
3830 public:
3832 
3833  void ProcessSubScript(const CScript &subscript, UniValue &obj) const {
3834  // Always present: script type and redeemscript
3835  std::vector<std::vector<uint8_t>> solutions_data;
3836  TxoutType which_type = Solver(subscript, solutions_data);
3837  obj.pushKV("script", GetTxnOutputType(which_type));
3838  obj.pushKV("hex", HexStr(subscript));
3839 
3840  CTxDestination embedded;
3841  if (ExtractDestination(subscript, embedded)) {
3842  // Only when the script corresponds to an address.
3843  UniValue subobj(UniValue::VOBJ);
3844  UniValue detail = DescribeAddress(embedded);
3845  subobj.pushKVs(detail);
3846  UniValue wallet_detail = std::visit(*this, embedded);
3847  subobj.pushKVs(wallet_detail);
3848  subobj.pushKV("address", EncodeDestination(embedded, GetConfig()));
3849  subobj.pushKV("scriptPubKey", HexStr(subscript));
3850  // Always report the pubkey at the top level, so that
3851  // `getnewaddress()['pubkey']` always works.
3852  if (subobj.exists("pubkey")) {
3853  obj.pushKV("pubkey", subobj["pubkey"]);
3854  }
3855  obj.pushKV("embedded", std::move(subobj));
3856  } else if (which_type == TxoutType::MULTISIG) {
3857  // Also report some information on multisig scripts (which do not
3858  // have a corresponding address).
3859  // TODO: abstract out the common functionality between this logic
3860  // and ExtractDestinations.
3861  obj.pushKV("sigsrequired", solutions_data[0][0]);
3862  UniValue pubkeys(UniValue::VARR);
3863  for (size_t i = 1; i < solutions_data.size() - 1; ++i) {
3864  CPubKey key(solutions_data[i].begin(), solutions_data[i].end());
3865  pubkeys.push_back(HexStr(key));
3866  }
3867  obj.pushKV("pubkeys", std::move(pubkeys));
3868  }
3869  }
3870 
3872  : provider(_provider) {}
3873 
3874  UniValue operator()(const CNoDestination &dest) const {
3875  return UniValue(UniValue::VOBJ);
3876  }
3877 
3878  UniValue operator()(const PKHash &pkhash) const {
3879  CKeyID keyID(ToKeyID(pkhash));
3880  UniValue obj(UniValue::VOBJ);
3881  CPubKey vchPubKey;
3882  if (provider && provider->GetPubKey(keyID, vchPubKey)) {
3883  obj.pushKV("pubkey", HexStr(vchPubKey));
3884  obj.pushKV("iscompressed", vchPubKey.IsCompressed());
3885  }
3886  return obj;
3887  }
3888 
3889  UniValue operator()(const ScriptHash &scripthash) const {
3890  CScriptID scriptID(scripthash);
3891  UniValue obj(UniValue::VOBJ);
3892  CScript subscript;
3893  if (provider && provider->GetCScript(scriptID, subscript)) {
3894  ProcessSubScript(subscript, obj);
3895  }
3896  return obj;
3897  }
3898 };
3899 
3900 static UniValue DescribeWalletAddress(const CWallet *const pwallet,
3901  const CTxDestination &dest) {
3902  UniValue ret(UniValue::VOBJ);
3903  UniValue detail = DescribeAddress(dest);
3904  CScript script = GetScriptForDestination(dest);
3905  std::unique_ptr<SigningProvider> provider = nullptr;
3906  if (pwallet) {
3907  provider = pwallet->GetSolvingProvider(script);
3908  }
3909  ret.pushKVs(detail);
3910  ret.pushKVs(std::visit(DescribeWalletAddressVisitor(provider.get()), dest));
3911  return ret;
3912 }
3913 
3916  const bool verbose) {
3917  UniValue ret(UniValue::VOBJ);
3918  if (verbose) {
3919  ret.pushKV("name", data.GetLabel());
3920  }
3921  ret.pushKV("purpose", data.purpose);
3922  return ret;
3923 }
3924 
3926  return RPCHelpMan{
3927  "getaddressinfo",
3928  "Return information about the given bitcoin address.\n"
3929  "Some of the information will only be present if the address is in the "
3930  "active wallet.\n",
3931  {
3933  "The bitcoin address for which to get information."},
3934  },
3935  RPCResult{
3937  "",
3938  "",
3939  {
3940  {RPCResult::Type::STR, "address",
3941  "The bitcoin address validated."},
3942  {RPCResult::Type::STR_HEX, "scriptPubKey",
3943  "The hex-encoded scriptPubKey generated by the address."},
3944  {RPCResult::Type::BOOL, "ismine", "If the address is yours."},
3945  {RPCResult::Type::BOOL, "iswatchonly",
3946  "If the address is watchonly."},
3947  {RPCResult::Type::BOOL, "solvable",
3948  "If we know how to spend coins sent to this address, ignoring "
3949  "the possible lack of private keys."},
3950  {RPCResult::Type::STR, "desc", /* optional */ true,
3951  "A descriptor for spending coins sent to this address (only "
3952  "when solvable)."},
3953  {RPCResult::Type::BOOL, "isscript", "If the key is a script."},
3954  {RPCResult::Type::BOOL, "ischange",
3955  "If the address was used for change output."},
3956  {RPCResult::Type::STR, "script", /* optional */ true,
3957  "The output script type. Only if isscript is true and the "
3958  "redeemscript is known. Possible\n"
3959  " "
3960  "types: nonstandard, pubkey, pubkeyhash, scripthash, "
3961  "multisig, nulldata."},
3962  {RPCResult::Type::STR_HEX, "hex", /* optional */ true,
3963  "The redeemscript for the p2sh address."},
3965  "pubkeys",
3966  /* optional */ true,
3967  "Array of pubkeys associated with the known redeemscript "
3968  "(only if script is multisig).",
3969  {
3970  {RPCResult::Type::STR, "pubkey", ""},
3971  }},
3972  {RPCResult::Type::NUM, "sigsrequired", /* optional */ true,
3973  "The number of signatures required to spend multisig output "
3974  "(only if script is multisig)."},
3975  {RPCResult::Type::STR_HEX, "pubkey", /* optional */ true,
3976  "The hex value of the raw public key for single-key addresses "
3977  "(possibly embedded in P2SH)."},
3979  "embedded",
3980  /* optional */ true,
3981  "Information about the address embedded in P2SH, if "
3982  "relevant and known.",
3983  {
3985  "Includes all getaddressinfo output fields for the "
3986  "embedded address excluding metadata (timestamp, "
3987  "hdkeypath, hdseedid)\n"
3988  "and relation to the wallet (ismine, iswatchonly)."},
3989  }},
3990  {RPCResult::Type::BOOL, "iscompressed", /* optional */ true,
3991  "If the pubkey is compressed."},
3992  {RPCResult::Type::NUM_TIME, "timestamp", /* optional */ true,
3993  "The creation time of the key, if available, expressed in " +
3994  UNIX_EPOCH_TIME + "."},
3995  {RPCResult::Type::STR, "hdkeypath", /* optional */ true,
3996  "The HD keypath, if the key is HD and available."},
3997  {RPCResult::Type::STR_HEX, "hdseedid", /* optional */ true,
3998  "The Hash160 of the HD seed."},
3999  {RPCResult::Type::STR_HEX, "hdmasterfingerprint",
4000  /* optional */ true, "The fingerprint of the master key."},
4002  "labels",
4003  "Array of labels associated with the address. Currently "
4004  "limited to one label but returned\n"
4005  "as an array to keep the API stable if multiple labels are "
4006  "enabled in the future.",
4007  {
4008  {RPCResult::Type::STR, "label name",
4009  "Label name (defaults to \"\")."},
4010  }},
4011  }},
4012  RPCExamples{HelpExampleCli("getaddressinfo", EXAMPLE_ADDRESS) +
4013  HelpExampleRpc("getaddressinfo", EXAMPLE_ADDRESS)},
4014  [&](const RPCHelpMan &self, const Config &config,
4015  const JSONRPCRequest &request) -> UniValue {
4016  std::shared_ptr<CWallet> const wallet =
4017  GetWalletForJSONRPCRequest(request);
4018  if (!wallet) {
4019  return NullUniValue;
4020  }
4021  const CWallet *const pwallet = wallet.get();
4022 
4023  LOCK(pwallet->cs_wallet);
4024 
4025  UniValue ret(UniValue::VOBJ);
4026  CTxDestination dest = DecodeDestination(request.params[0].get_str(),
4027  wallet->GetChainParams());
4028  // Make sure the destination is valid
4029  if (!IsValidDestination(dest)) {
4031  "Invalid address");
4032  }
4033 
4034  std::string currentAddress = EncodeDestination(dest, config);
4035  ret.pushKV("address", currentAddress);
4036 
4037  CScript scriptPubKey = GetScriptForDestination(dest);
4038  ret.pushKV("scriptPubKey", HexStr(scriptPubKey));
4039 
4040  std::unique_ptr<SigningProvider> provider =
4041  pwallet->GetSolvingProvider(scriptPubKey);
4042 
4043  isminetype mine = pwallet->IsMine(dest);
4044  ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE));
4045 
4046  bool solvable = provider && IsSolvable(*provider, scriptPubKey);
4047  ret.pushKV("solvable", solvable);
4048 
4049  if (solvable) {
4050  ret.pushKV(
4051  "desc",
4052  InferDescriptor(scriptPubKey, *provider)->ToString());
4053  }
4054 
4055  ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY));
4056 
4057  UniValue detail = DescribeWalletAddress(pwallet, dest);
4058  ret.pushKVs(detail);
4059 
4060  ret.pushKV("ischange", ScriptIsChange(*pwallet, scriptPubKey));
4061 
4062  ScriptPubKeyMan *spk_man =
4063  pwallet->GetScriptPubKeyMan(scriptPubKey);
4064  if (spk_man) {
4065  if (const std::unique_ptr<CKeyMetadata> meta =
4066  spk_man->GetMetadata(dest)) {
4067  ret.pushKV("timestamp", meta->nCreateTime);
4068  if (meta->has_key_origin) {
4069  ret.pushKV("hdkeypath",
4070  WriteHDKeypath(meta->key_origin.path));
4071  ret.pushKV("hdseedid", meta->hd_seed_id.GetHex());
4072  ret.pushKV("hdmasterfingerprint",
4073  HexStr(meta->key_origin.fingerprint));
4074  }
4075  }
4076  }
4077 
4078  // Return a `labels` array containing the label associated with the
4079  // address, equivalent to the `label` field above. Currently only
4080  // one label can be associated with an address, but we return an
4081  // array so the API remains stable if we allow multiple labels to be
4082  // associated with an address in the future.
4083  UniValue labels(UniValue::VARR);
4084  const auto *address_book_entry =
4085  pwallet->FindAddressBookEntry(dest);
4086  if (address_book_entry) {
4087  labels.push_back(address_book_entry->GetLabel());
4088  }
4089  ret.pushKV("labels", std::move(labels));
4090 
4091  return ret;
4092  },
4093  };
4094 }
4095 
4097  return RPCHelpMan{
4098  "getaddressesbylabel",
4099  "Returns the list of addresses assigned the specified label.\n",
4100  {
4101  {"label", RPCArg::Type::STR, RPCArg::Optional::NO, "The label."},
4102  },
4104  "",
4105  "json object with addresses as keys",
4106  {
4108  "address",
4109  "Information about address",
4110  {
4111  {RPCResult::Type::STR, "purpose",
4112  "Purpose of address (\"send\" for sending address, "
4113  "\"receive\" for receiving address)"},
4114  }},
4115  }},
4116  RPCExamples{HelpExampleCli("getaddressesbylabel", "\"tabby\"") +
4117  HelpExampleRpc("getaddressesbylabel", "\"tabby\"")},
4118  [&](const RPCHelpMan &self, const Config &config,
4119  const JSONRPCRequest &request) -> UniValue {
4120  std::shared_ptr<CWallet> const wallet =
4121  GetWalletForJSONRPCRequest(request);
4122  if (!wallet) {
4123  return NullUniValue;
4124  }
4125  const CWallet *const pwallet = wallet.get();
4126 
4127  LOCK(pwallet->cs_wallet);
4128 
4129  std::string label = LabelFromValue(request.params[0]);
4130 
4131  // Find all addresses that have the given label
4132  UniValue ret(UniValue::VOBJ);
4133  std::set<std::string> addresses;
4134  for (const std::pair<const CTxDestination, CAddressBookData> &item :
4135  pwallet->m_address_book) {
4136  if (item.second.IsChange()) {
4137  continue;
4138  }
4139  if (item.second.GetLabel() == label) {
4140  std::string address = EncodeDestination(item.first, config);
4141  // CWallet::m_address_book is not expected to contain
4142  // duplicate address strings, but build a separate set as a
4143  // precaution just in case it does.
4144  CHECK_NONFATAL(addresses.emplace(address).second);
4145  // UniValue::pushKV checks if the key exists in O(N)
4146  // and since duplicate addresses are unexpected (checked
4147  // with std::set in O(log(N))), UniValue::__pushKV is used
4148  // instead, which currently is O(1).
4149  ret.__pushKV(address,
4150  AddressBookDataToJSON(item.second, false));
4151  }
4152  }
4153 
4154  if (ret.empty()) {
4155  throw JSONRPCError(
4157  std::string("No addresses with label " + label));
4158  }
4159 
4160  return ret;
4161  },
4162  };
4163 }
4164 
4166  return RPCHelpMan{
4167  "listlabels",
4168  "Returns the list of all labels, or labels that are assigned to "
4169  "addresses with a specific purpose.\n",
4170  {
4172  "Address purpose to list labels for ('send','receive'). An empty "
4173  "string is the same as not providing this argument."},
4174  },
4176  "",
4177  "",
4178  {
4179  {RPCResult::Type::STR, "label", "Label name"},
4180  }},
4181  RPCExamples{"\nList all labels\n" + HelpExampleCli("listlabels", "") +
4182  "\nList labels that have receiving addresses\n" +
4183  HelpExampleCli("listlabels", "receive") +
4184  "\nList labels that have sending addresses\n" +
4185  HelpExampleCli("listlabels", "send") +
4186  "\nAs a JSON-RPC call\n" +
4187  HelpExampleRpc("listlabels", "receive")},
4188  [&](const RPCHelpMan &self, const Config &config,
4189  const JSONRPCRequest &request) -> UniValue {
4190  std::shared_ptr<CWallet> const wallet =
4191  GetWalletForJSONRPCRequest(request);
4192  if (!wallet) {
4193  return NullUniValue;
4194  }
4195  const CWallet *const pwallet = wallet.get();
4196 
4197  LOCK(pwallet->cs_wallet);
4198 
4199  std::string purpose;
4200  if (!request.params[0].isNull()) {
4201  purpose = request.params[0].get_str();
4202  }
4203 
4204  // Add to a set to sort by label name, then insert into Univalue
4205  // array
4206  std::set<std::string> label_set;
4207  for (const std::pair<const CTxDestination, CAddressBookData>
4208  &entry : pwallet->m_address_book) {
4209  if (entry.second.IsChange()) {
4210  continue;
4211  }
4212  if (purpose.empty() || entry.second.purpose == purpose) {
4213  label_set.insert(entry.second.GetLabel());
4214  }
4215  }
4216 
4217  UniValue ret(UniValue::VARR);
4218  for (const std::string &name : label_set) {
4219  ret.push_back(name);
4220  }
4221 
4222  return ret;
4223  },
4224  };
4225 }
4226 
4227 static RPCHelpMan send() {
4228  return RPCHelpMan{
4229  "send",
4230  "EXPERIMENTAL warning: this call may be changed in future releases.\n"
4231  "\nSend a transaction.\n",
4232  {
4233  {"outputs",
4236  "A JSON array with outputs (key-value pairs), where none of "
4237  "the keys are duplicated.\n"
4238  "That is, each address can only appear once and there can only "
4239  "be one 'data' object.\n"
4240  "For convenience, a dictionary, which holds the key-value "
4241  "pairs directly, is also accepted.",
4242  {
4243  {
4244  "",
4247  "",
4248  {
4250  "A key-value pair. The key (string) is the "
4251  "bitcoin address, the value (float or string) is "
4252  "the amount in " +
4253  Currency::get().ticker + ""},
4254  },
4255  },
4256  {
4257  "",
4260  "",
4261  {
4263  "A key-value pair. The key must be \"data\", the "
4264  "value is hex-encoded data"},
4265  },
4266  },
4267  },
4268  RPCArgOptions{.skip_type_check = true}},
4269  {"options",
4272  "",
4273  {
4274  {"add_inputs", RPCArg::Type::BOOL, RPCArg::Default{false},
4275  "If inputs are specified, automatically include more if they "
4276  "are not enough."},
4277  {"include_unsafe", RPCArg::Type::BOOL, RPCArg::Default{false},
4278  "Include inputs that are not safe to spend (unconfirmed "
4279  "transactions from outside keys).\n"
4280  "Warning: the resulting transaction may become invalid if "
4281  "one of the unsafe inputs disappears.\n"
4282  "If that happens, you will need to fund the transaction with "
4283  "different inputs and republish it."},
4284  {"add_to_wallet", RPCArg::Type::BOOL, RPCArg::Default{true},
4285  "When false, returns a serialized transaction which will not "
4286  "be added to the wallet or broadcast"},
4287  {"change_address", RPCArg::Type::STR_HEX,
4288  RPCArg::DefaultHint{"pool address"},
4289  "The bitcoin address to receive the change"},
4290  {"change_position", RPCArg::Type::NUM,
4291  RPCArg::DefaultHint{"random"},
4292  "The index of the change output"},
4293  {"fee_rate", RPCArg::Type::AMOUNT,
4295  "not set: makes wallet determine the fee"},
4296  "Set a specific fee rate in " + Currency::get().ticker +
4297  "/kB"},
4298  {"include_watching", RPCArg::Type::BOOL,
4300  "true for watch-only wallets, otherwise false"},
4301  "Also select inputs which are watch only.\n"
4302  "Only solvable inputs can be used. Watch-only destinations "
4303  "are solvable if the public key and/or output script was "
4304  "imported,\n"
4305  "e.g. with 'importpubkey' or 'importmulti' with the "
4306  "'pubkeys' or 'desc' field."},
4307  {
4308  "inputs",
4311  "Specify inputs instead of adding them automatically. A "
4312  "JSON array of JSON objects",
4313  {
4315  "The transaction id"},
4317  "The output number"},
4319  "The sequence number"},
4320  },
4321  },
4322  {"locktime", RPCArg::Type::NUM, RPCArg::Default{0},
4323  "Raw locktime. Non-0 value also locktime-activates inputs"},
4324  {"lock_unspents", RPCArg::Type::BOOL, RPCArg::Default{false},
4325  "Lock selected unspent outputs"},
4326  {"psbt", RPCArg::Type::BOOL, RPCArg::DefaultHint{"automatic"},
4327  "Always return a PSBT, implies add_to_wallet=false."},
4328  {
4329  "subtract_fee_from_outputs",
4332  "Outputs to subtract the fee from, specified as integer "
4333  "indices.\n"
4334  "The fee will be equally deducted from the amount of each "
4335  "specified output.\n"
4336  "Those recipients will receive less bitcoins than you "
4337  "enter in their corresponding amount field.\n"
4338  "If no outputs are specified here, the sender pays the "
4339  "fee.",
4340  {
4341  {"vout_index", RPCArg::Type::NUM,
4343  "The zero-based output index, before a change output "
4344  "is added."},
4345  },
4346  },
4347  },
4348  RPCArgOptions{.oneline_description = "options"}},
4349  },
4350  RPCResult{
4352  "",
4353  "",
4354  {{RPCResult::Type::BOOL, "complete",
4355  "If the transaction has a complete set of signatures"},
4356  {RPCResult::Type::STR_HEX, "txid",
4357  "The transaction id for the send. Only 1 transaction is created "
4358  "regardless of the number of addresses."},
4359  {RPCResult::Type::STR_HEX, "hex",
4360  "If add_to_wallet is false, the hex-encoded raw transaction with "
4361  "signature(s)"},
4362  {RPCResult::Type::STR, "psbt",
4363  "If more signatures are needed, or if add_to_wallet is false, "
4364  "the base64-encoded (partially) signed transaction"}}},
4365  RPCExamples{
4366  ""
4367  "\nSend with a fee rate of 10 XEC/kB\n" +
4368  HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS +
4369  "\": 100000}' '{\"fee_rate\": 10}'\n") +
4370  "\nCreate a transaction with a specific input, and return "
4371  "result without adding to wallet or broadcasting to the "
4372  "network\n" +
4373  HelpExampleCli("send",
4374  "'{\"" + EXAMPLE_ADDRESS +
4375  "\": 100000}' '{\"add_to_wallet\": "
4376  "false, \"inputs\": "
4377  "[{\"txid\":"
4378  "\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b565"
4379  "5e72f463568df1aadf0\", \"vout\":1}]}'")},
4380  [&](const RPCHelpMan &self, const Config &config,
4381  const JSONRPCRequest &request) -> UniValue {
4382  std::shared_ptr<CWallet> const wallet =
4383  GetWalletForJSONRPCRequest(request);
4384  if (!wallet) {
4385  return NullUniValue;
4386  }
4387  CWallet *const pwallet = wallet.get();
4388 
4389  UniValue options = request.params[1];
4390  if (options.exists("changeAddress")) {
4391  throw JSONRPCError(RPC_INVALID_PARAMETER, "Use change_address");
4392  }
4393  if (options.exists("changePosition")) {
4395  "Use change_position");
4396  }
4397  if (options.exists("includeWatching")) {
4399  "Use include_watching");
4400  }
4401  if (options.exists("lockUnspents")) {
4402  throw JSONRPCError(RPC_INVALID_PARAMETER, "Use lock_unspents");
4403  }
4404  if (options.exists("subtractFeeFromOutputs")) {
4406  "Use subtract_fee_from_outputs");
4407  }
4408  if (options.exists("feeRate")) {
4409  throw JSONRPCError(RPC_INVALID_PARAMETER, "Use fee_rate");
4410  }
4411 
4412  const bool psbt_opt_in =
4413  options.exists("psbt") && options["psbt"].get_bool();
4414 
4415  Amount fee;
4416  int change_position;
4418  wallet->GetChainParams(), options["inputs"], request.params[0],
4419  options["locktime"]);
4420  CCoinControl coin_control;
4421  // Automatically select coins, unless at least one is manually
4422  // selected. Can be overridden by options.add_inputs.
4423  coin_control.m_add_inputs = rawTx.vin.size() == 0;
4424  FundTransaction(pwallet, rawTx, fee, change_position, options,
4425  coin_control);
4426 
4427  bool add_to_wallet = true;
4428  if (options.exists("add_to_wallet")) {
4429  add_to_wallet = options["add_to_wallet"].get_bool();
4430  }
4431 
4432  // Make a blank psbt
4433  PartiallySignedTransaction psbtx(rawTx);
4434 
4435  // Fill transaction with our data and sign
4436  bool complete = true;
4437  const TransactionError err = pwallet->FillPSBT(
4438  psbtx, complete, SigHashType().withForkId(), true, false);
4439  if (err != TransactionError::OK) {
4440  throw JSONRPCTransactionError(err);
4441  }
4442 
4443  CMutableTransaction mtx;
4444  complete = FinalizeAndExtractPSBT(psbtx, mtx);
4445 
4446  UniValue result(UniValue::VOBJ);
4447 
4448  if (psbt_opt_in || !complete || !add_to_wallet) {
4449  // Serialize the PSBT
4451  ssTx << psbtx;
4452  result.pushKV("psbt", EncodeBase64(ssTx.str()));
4453  }
4454 
4455  if (complete) {
4456  std::string err_string;
4457  std::string hex = EncodeHexTx(CTransaction(mtx));
4458  CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
4459  result.pushKV("txid", tx->GetHash().GetHex());
4460  if (add_to_wallet && !psbt_opt_in) {
4461  pwallet->CommitTransaction(tx, {}, {} /* orderForm */);
4462  } else {
4463  result.pushKV("hex", hex);
4464  }
4465  }
4466  result.pushKV("complete", complete);
4467 
4468  return result;
4469  }};
4470 }
4471 
4473  return RPCHelpMan{
4474  "sethdseed",
4475  "Set or generate a new HD wallet seed. Non-HD wallets will not be "
4476  "upgraded to being a HD wallet. Wallets that are already\n"
4477  "HD will have a new HD seed set so that new keys added to the keypool "
4478  "will be derived from this new seed.\n"
4479  "\nNote that you will need to MAKE A NEW BACKUP of your wallet after "
4480  "setting the HD wallet seed.\n" +
4482  {
4483  {"newkeypool", RPCArg::Type::BOOL, RPCArg::Default{true},
4484  "Whether to flush old unused addresses, including change "
4485  "addresses, from the keypool and regenerate it.\n"
4486  " If true, the next address from "
4487  "getnewaddress and change address from getrawchangeaddress will "
4488  "be from this new seed.\n"
4489  " If false, addresses (including "
4490  "change addresses if the wallet already had HD Chain Split "
4491  "enabled) from the existing\n"
4492  " keypool will be used until it has "
4493  "been depleted."},
4494  {"seed", RPCArg::Type::STR, RPCArg::DefaultHint{"random seed"},
4495  "The WIF private key to use as the new HD seed.\n"
4496  " The seed value can be retrieved "
4497  "using the dumpwallet command. It is the private key marked "
4498  "hdseed=1"},
4499  },
4501  RPCExamples{HelpExampleCli("sethdseed", "") +
4502  HelpExampleCli("sethdseed", "false") +
4503  HelpExampleCli("sethdseed", "true \"wifkey\"") +
4504  HelpExampleRpc("sethdseed", "true, \"wifkey\"")},
4505  [&](const RPCHelpMan &self, const Config &config,
4506  const JSONRPCRequest &request) -> UniValue {
4507  std::shared_ptr<CWallet> const wallet =
4508  GetWalletForJSONRPCRequest(request);
4509  if (!wallet) {
4510  return NullUniValue;
4511  }
4512  CWallet *const pwallet = wallet.get();
4513 
4514  LegacyScriptPubKeyMan &spk_man =
4515  EnsureLegacyScriptPubKeyMan(*pwallet, true);
4516 
4519  "Cannot set a HD seed to a wallet with "
4520  "private keys disabled");
4521  }
4522 
4523  LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore);
4524 
4525  // Do not do anything to non-HD wallets
4526  if (!pwallet->CanSupportFeature(FEATURE_HD)) {
4527  throw JSONRPCError(
4529  "Cannot set a HD seed on a non-HD wallet. Use the "
4530  "upgradewallet RPC in order to upgrade a non-HD wallet "
4531  "to HD");
4532  }
4533 
4534  EnsureWalletIsUnlocked(pwallet);
4535 
4536  bool flush_key_pool = true;
4537  if (!request.params[0].isNull()) {
4538  flush_key_pool = request.params[0].get_bool();
4539  }
4540 
4541  CPubKey master_pub_key;
4542  if (request.params[1].isNull()) {
4543  master_pub_key = spk_man.GenerateNewSeed();
4544  } else {
4545  CKey key = DecodeSecret(request.params[1].get_str());
4546  if (!key.IsValid()) {
4548  "Invalid private key");
4549  }
4550 
4551  if (HaveKey(spk_man, key)) {
4552  throw JSONRPCError(
4554  "Already have this key (either as an HD seed or "
4555  "as a loose private key)");
4556  }
4557 
4558  master_pub_key = spk_man.DeriveNewSeed(key);
4559  }
4560 
4561  spk_man.SetHDSeed(master_pub_key);
4562  if (flush_key_pool) {
4563  spk_man.NewKeyPool();
4564  }
4565 
4566  return NullUniValue;
4567  },
4568  };
4569 }
4570 
4572  return RPCHelpMan{
4573  "walletprocesspsbt",
4574  "Update a PSBT with input information from our wallet and then sign "
4575  "inputs that we can sign for." +
4577  {
4579  "The transaction base64 string"},
4580  {"sign", RPCArg::Type::BOOL, RPCArg::Default{true},
4581  "Also sign the transaction when updating"},
4582  {"sighashtype", RPCArg::Type::STR, RPCArg::Default{"ALL|FORKID"},
4583  "The signature hash type to sign with if not specified by "
4584  "the PSBT. Must be one of\n"
4585  " \"ALL|FORKID\"\n"
4586  " \"NONE|FORKID\"\n"
4587  " \"SINGLE|FORKID\"\n"
4588  " \"ALL|FORKID|ANYONECANPAY\"\n"
4589  " \"NONE|FORKID|ANYONECANPAY\"\n"
4590  " \"SINGLE|FORKID|ANYONECANPAY\""},
4591  {"bip32derivs", RPCArg::Type::BOOL, RPCArg::Default{true},
4592  "Includes the BIP 32 derivation paths for public keys if we know "
4593  "them"},
4594  },
4596  "",
4597  "",
4598  {
4599  {RPCResult::Type::STR, "psbt",
4600  "The base64-encoded partially signed transaction"},
4601  {RPCResult::Type::BOOL, "complete",
4602  "If the transaction has a complete set of signatures"},
4603  }},
4604  RPCExamples{HelpExampleCli("walletprocesspsbt", "\"psbt\"")},
4605  [&](const RPCHelpMan &self, const Config &config,
4606  const JSONRPCRequest &request) -> UniValue {
4607  std::shared_ptr<CWallet> const wallet =
4608  GetWalletForJSONRPCRequest(request);
4609  if (!wallet) {
4610  return NullUniValue;
4611  }
4612  const CWallet *const pwallet = wallet.get();
4613 
4614  // Unserialize the transaction
4616  std::string error;
4617  if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
4619  strprintf("TX decode failed %s", error));
4620  }
4621 
4622  // Get the sighash type
4623  SigHashType nHashType = ParseSighashString(request.params[2]);
4624  if (!nHashType.hasForkId()) {
4626  "Signature must use SIGHASH_FORKID");
4627  }
4628 
4629  // Fill transaction with our data and also sign
4630  bool sign = request.params[1].isNull()
4631  ? true
4632  : request.params[1].get_bool();
4633  bool bip32derivs = request.params[3].isNull()
4634  ? true
4635  : request.params[3].get_bool();
4636  bool complete = true;
4637  const TransactionError err = pwallet->FillPSBT(
4638  psbtx, complete, nHashType, sign, bip32derivs);
4639  if (err != TransactionError::OK) {
4640  throw JSONRPCTransactionError(err);
4641  }
4642 
4643  UniValue result(UniValue::VOBJ);
4645  ssTx << psbtx;
4646  result.pushKV("psbt", EncodeBase64(ssTx.str()));
4647  result.pushKV("complete", complete);
4648 
4649  return result;
4650  },
4651  };
4652 }
4653 
4655  const auto &ticker = Currency::get().ticker;
4656  return RPCHelpMan{
4657  "walletcreatefundedpsbt",
4658  "Creates and funds a transaction in the Partially Signed Transaction "
4659  "format.\n"
4660  "Implements the Creator and Updater roles.\n",
4661  {
4662  {
4663  "inputs",
4666  "Leave empty to add inputs automatically. See add_inputs "
4667  "option.",
4668  {
4669  {
4670  "",
4673  "",
4674  {
4675  {"txid", RPCArg::Type::STR_HEX,
4676  RPCArg::Optional::NO, "The transaction id"},
4678  "The output number"},
4679  {"sequence", RPCArg::Type::NUM,
4681  "depends on the value of the 'locktime' and "
4682  "'options.replaceable' arguments"},
4683  "The sequence number"},
4684  },
4685  },
4686  },
4687  },
4688  {"outputs",
4691  "The outputs (key-value pairs), where none of "
4692  "the keys are duplicated.\n"
4693  "That is, each address can only appear once and there can only "
4694  "be one 'data' object.\n"
4695  "For compatibility reasons, a dictionary, which holds the "
4696  "key-value pairs directly, is also\n"
4697  " accepted as second parameter.",
4698  {
4699  {
4700  "",
4703  "",
4704  {
4706  "A key-value pair. The key (string) is the "
4707  "bitcoin address, the value (float or string) is "
4708  "the amount in " +
4709  ticker + ""},
4710  },
4711  },
4712  {
4713  "",
4716  "",
4717  {
4719  "A key-value pair. The key must be \"data\", the "
4720  "value is hex-encoded data"},
4721  },
4722  },
4723  },
4724  RPCArgOptions{.skip_type_check = true}},
4725  {"locktime", RPCArg::Type::NUM, RPCArg::Default{0},
4726  "Raw locktime. Non-0 value also locktime-activates inputs\n"
4727  " Allows this transaction to be "
4728  "replaced by a transaction with higher fees. If provided, it is "
4729  "an error if explicit sequence numbers are incompatible."},
4730  {"options",
4733  "",
4734  {
4735  {"add_inputs", RPCArg::Type::BOOL, RPCArg::Default{false},
4736  "If inputs are specified, automatically include more if they "
4737  "are not enough."},
4738  {"include_unsafe", RPCArg::Type::BOOL, RPCArg::Default{false},
4739  "Include inputs that are not safe to spend (unconfirmed "
4740  "transactions from outside keys).\n"
4741  "Warning: the resulting transaction may become invalid if "
4742  "one of the unsafe inputs disappears.\n"
4743  "If that happens, you will need to fund the transaction with "
4744  "different inputs and republish it."},
4745  {"changeAddress", RPCArg::Type::STR_HEX,
4746  RPCArg::DefaultHint{"pool address"},
4747  "The bitcoin address to receive the change"},
4748  {"changePosition", RPCArg::Type::NUM,
4749  RPCArg::DefaultHint{"random"},
4750  "The index of the change output"},
4751  {"includeWatching", RPCArg::Type::BOOL,
4753  "true for watch-only wallets, otherwise false"},
4754  "Also select inputs which are watch only"},
4755  {"lockUnspents", RPCArg::Type::BOOL, RPCArg::Default{false},
4756  "Lock selected unspent outputs"},
4757  {"feeRate", RPCArg::Type::AMOUNT,
4759  "not set: makes wallet determine the fee"},
4760  "Set a specific fee rate in " + ticker + "/kB"},
4761  {
4762  "subtractFeeFromOutputs",
4765  "The outputs to subtract the fee from.\n"
4766  " The fee will be equally "
4767  "deducted from the amount of each specified output.\n"
4768  " Those recipients will "
4769  "receive less bitcoins than you enter in their "
4770  "corresponding amount field.\n"
4771  " If no outputs are "
4772  "specified here, the sender pays the fee.",
4773  {
4774  {"vout_index", RPCArg::Type::NUM,
4776  "The zero-based output index, before a change output "
4777  "is added."},
4778  },
4779  },
4780  },
4781  RPCArgOptions{.oneline_description = "options"}},
4782  {"bip32derivs", RPCArg::Type::BOOL, RPCArg::Default{true},
4783  "Includes the BIP 32 derivation paths for public keys if we know "
4784  "them"},
4785  },
4787  "",
4788  "",
4789  {
4790  {RPCResult::Type::STR, "psbt",
4791  "The resulting raw transaction (base64-encoded string)"},
4793  "Fee in " + ticker + " the resulting transaction pays"},
4794  {RPCResult::Type::NUM, "changepos",
4795  "The position of the added change output, or -1"},
4796  }},
4797  RPCExamples{
4798  "\nCreate a transaction with no inputs\n" +
4799  HelpExampleCli("walletcreatefundedpsbt",
4800  "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" "
4801  "\"[{\\\"data\\\":\\\"00010203\\\"}]\"")},
4802  [&](const RPCHelpMan &self, const Config &config,
4803  const JSONRPCRequest &request) -> UniValue {
4804  std::shared_ptr<CWallet> const wallet =
4805  GetWalletForJSONRPCRequest(request);
4806  if (!wallet) {
4807  return NullUniValue;
4808  }
4809  CWallet *const pwallet = wallet.get();
4810 
4811  Amount fee;
4812  int change_position;
4814  wallet->GetChainParams(), request.params[0], request.params[1],
4815  request.params[2]);
4816  CCoinControl coin_control;
4817  // Automatically select coins, unless at least one is manually
4818  // selected. Can be overridden by options.add_inputs.
4819  coin_control.m_add_inputs = rawTx.vin.size() == 0;
4820  FundTransaction(pwallet, rawTx, fee, change_position,
4821  request.params[3], coin_control);
4822 
4823  // Make a blank psbt
4824  PartiallySignedTransaction psbtx(rawTx);
4825 
4826  // Fill transaction with out data but don't sign
4827  bool bip32derivs = request.params[4].isNull()
4828  ? true
4829  : request.params[4].get_bool();
4830  bool complete = true;
4831  const TransactionError err =
4832  pwallet->FillPSBT(psbtx, complete, SigHashType().withForkId(),
4833  false, bip32derivs);
4834  if (err != TransactionError::OK) {
4835  throw JSONRPCTransactionError(err);
4836  }
4837 
4838  // Serialize the PSBT
4840  ssTx << psbtx;
4841 
4842  UniValue result(UniValue::VOBJ);
4843  result.pushKV("psbt", EncodeBase64(ssTx.str()));
4844  result.pushKV("fee", fee);
4845  result.pushKV("changepos", change_position);
4846  return result;
4847  },
4848  };
4849 }
4850 
4852  return RPCHelpMan{
4853  "upgradewallet",
4854  "Upgrade the wallet. Upgrades to the latest version if no "
4855  "version number is specified\n"
4856  "New keys may be generated and a new wallet backup will need to "
4857  "be made.",
4859  "The version number to upgrade to. Default is the latest "
4860  "wallet version"}},
4862  RPCExamples{HelpExampleCli("upgradewallet", "200300") +
4863  HelpExampleRpc("upgradewallet", "200300")},
4864  [&](const RPCHelpMan &self, const Config &config,
4865  const JSONRPCRequest &request) -> UniValue {
4866  std::shared_ptr<CWallet> const wallet =
4867  GetWalletForJSONRPCRequest(request);
4868  if (!wallet) {
4869  return NullUniValue;
4870  }
4871  CWallet *const pwallet = wallet.get();
4872 
4873  EnsureWalletIsUnlocked(pwallet);
4874 
4875  int version = 0;
4876  if (!request.params[0].isNull()) {
4877  version = request.params[0].get_int();
4878  }
4880  if (!pwallet->UpgradeWallet(version, error)) {
4881  throw JSONRPCError(RPC_WALLET_ERROR, error.original);
4882  }
4883  return error.original;
4884  },
4885  };
4886 }
4887 
4889 
4891  return RPCHelpMan{
4892  "createwallettransaction",
4893  "Create a transaction sending an amount to a given address.\n" +
4895  {
4897  "The bitcoin address to send to."},
4899  "The amount in " + Currency::get().ticker + " to send. eg 0.1"},
4900  },
4901  RPCResult{RPCResult::Type::STR_HEX, "txid", "The transaction id."},
4902  RPCExamples{
4903  HelpExampleCli("createwallettransaction",
4904  "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 100000") +
4905  HelpExampleRpc("createwallettransaction",
4906  "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 100000")},
4907  [&](const RPCHelpMan &self, const Config &config,
4908  const JSONRPCRequest &request) -> UniValue {
4909  std::shared_ptr<CWallet> const wallet =
4910  GetWalletForJSONRPCRequest(request);
4911  if (!wallet) {
4912  return NullUniValue;
4913  }
4914  CWallet *const pwallet = wallet.get();
4915 
4916  // Make sure the results are valid at least up to the most recent
4917  // block the user could have gotten from another RPC command prior
4918  // to now
4919  pwallet->BlockUntilSyncedToCurrentChain();
4920 
4921  LOCK(pwallet->cs_wallet);
4922 
4923  EnsureWalletIsUnlocked(pwallet);
4924 
4925  UniValue address_amounts(UniValue::VOBJ);
4926  const std::string address = request.params[0].get_str();
4927  address_amounts.pushKV(address, request.params[1]);
4928  UniValue subtractFeeFromAmount(UniValue::VARR);
4929 
4930  std::vector<CRecipient> recipients;
4931  ParseRecipients(address_amounts, subtractFeeFromAmount, recipients,
4932  wallet->GetChainParams());
4933 
4934  CCoinControl coin_control;
4935  return SendMoney(pwallet, coin_control, recipients, {}, false);
4936  },
4937  };
4938 }
4939 
4941  // clang-format off
4942  static const CRPCCommand commands[] = {
4943  // category actor (function)
4944  // ------------------ ----------------------
4945  { "rawtransactions", fundrawtransaction, },
4946  { "wallet", abandontransaction, },
4947  { "wallet", addmultisigaddress, },
4948  { "wallet", createwallet, },
4949  { "wallet", getaddressesbylabel, },
4950  { "wallet", getaddressinfo, },
4951  { "wallet", getbalance, },
4952  { "wallet", getnewaddress, },
4953  { "wallet", getrawchangeaddress, },
4954  { "wallet", getreceivedbyaddress, },
4955  { "wallet", getreceivedbylabel, },
4956  { "wallet", gettransaction, },
4957  { "wallet", getunconfirmedbalance, },
4958  { "wallet", getbalances, },
4959  { "wallet", getwalletinfo, },
4960  { "wallet", keypoolrefill, },
4961  { "wallet", listaddressgroupings, },
4962  { "wallet", listlabels, },
4963  { "wallet", listlockunspent, },
4964  { "wallet", listreceivedbyaddress, },
4965  { "wallet", listreceivedbylabel, },
4966  { "wallet", listsinceblock, },
4967  { "wallet", listtransactions, },
4968  { "wallet", listunspent, },
4969  { "wallet", listwalletdir, },
4970  { "wallet", listwallets, },
4971  { "wallet", loadwallet, },
4972  { "wallet", lockunspent, },
4973  { "wallet", rescanblockchain, },
4974  { "wallet", send, },
4975  { "wallet", sendmany, },
4976  { "wallet", sendtoaddress, },
4977  { "wallet", sethdseed, },
4978  { "wallet", setlabel, },
4979  { "wallet", settxfee, },
4980  { "wallet", setwalletflag, },
4981  { "wallet", signmessage, },
4982  { "wallet", signrawtransactionwithwallet, },
4983  { "wallet", unloadwallet, },
4984  { "wallet", upgradewallet, },
4985  { "wallet", walletcreatefundedpsbt, },
4986  { "wallet", walletprocesspsbt, },
4987  // For testing purpose
4988  { "hidden", createwallettransaction, },
4989  };
4990  // clang-format on
4991 
4992  return commands;
4993 }
static constexpr Amount MAX_MONEY
No amount larger than this (in satoshi) is valid.
Definition: amount.h:165
std::string WriteHDKeypath(const std::vector< uint32_t > &keypath)
Write HD keypaths as strings.
Definition: bip32.cpp:66
int flags
Definition: bitcoin-tx.cpp:543
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:53
Address book data.
Definition: wallet.h:199
const std::string & GetLabel() const
Definition: wallet.h:213
std::string purpose
Definition: wallet.h:205
BlockHash hashPrevBlock
Definition: block.h:27
bool IsNull() const
Definition: block.h:49
Definition: block.h:60
std::vector< CTransactionRef > vtx
Definition: block.h:63
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
Definition: chainparams.h:80
Coin Control Features.
Definition: coincontrol.h:21
int m_max_depth
Maximum chain depth value for coin availability.
Definition: coincontrol.h:48
bool fAllowWatchOnly
Includes watch only addresses which are solvable.
Definition: coincontrol.h:34
int m_min_depth
Minimum chain depth value for coin availability.
Definition: coincontrol.h:46
std::optional< CFeeRate > m_feerate
Override the wallet's m_pay_tx_fee if set.
Definition: coincontrol.h:38
bool fOverrideFeeRate
Override automatic min/max checks on fee, m_feerate must be set if true.
Definition: coincontrol.h:36
bool m_add_inputs
If false, only selected inputs are used.
Definition: coincontrol.h:27
CTxDestination destChange
Definition: coincontrol.h:23
bool m_avoid_address_reuse
Forbids inclusion of dirty (previously used) addresses.
Definition: coincontrol.h:44
bool m_include_unsafe_inputs
If false, only safe inputs will be used (confirmed or self transfers)
Definition: coincontrol.h:29
bool m_avoid_partial_spends
Avoid partial use of funds sent to a given address.
Definition: coincontrol.h:42
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:177
std::string str() const
Definition: streams.h:212
Fee rate in satoshis per kilobyte: Amount / kB.
Definition: feerate.h:21
std::string ToString() const
Definition: feerate.cpp:57
Amount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
Definition: feerate.h:54
CKeyID seed_id
seed hash160
Definition: walletdb.h:92
An encapsulated secp256k1 private key.
Definition: key.h:28
const uint8_t * begin() const
Definition: key.h:90
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:94
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
Definition: key.h:98
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:210
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:76
const uint8_t * end() const
Definition: key.h:91
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:22
A mutable version of CTransaction.
Definition: transaction.h:274
std::vector< CTxOut > vout
Definition: transaction.h:277
std::vector< CTxIn > vin
Definition: transaction.h:276
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:20
uint32_t GetN() const
Definition: transaction.h:36
Definition: spend.h:19
An encapsulated public key.
Definition: pubkey.h:31
bool IsCompressed() const
Check whether this is a compressed public key.
Definition: pubkey.h:154
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:137
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:431
bool IsPayToScriptHash() const
Definition: script.cpp:373
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:24
The basic transaction that is broadcasted on the network and contained in blocks.
Definition: transaction.h:192
An input of a transaction.
Definition: transaction.h:59
COutPoint prevout
Definition: transaction.h:61
An output of a transaction.
Definition: transaction.h:128
CScript scriptPubKey
Definition: transaction.h:131
Amount nValue
Definition: transaction.h:130
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:254
std::unique_ptr< SigningProvider > GetSolvingProvider(const CScript &script) const
Get the SigningProvider for a script.
Definition: wallet.cpp:3255
BlockHash GetLastBlockHash() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.h:1026
double ScanningProgress() const
Definition: wallet.h:520
TxItems wtxOrdered
Definition: wallet.h:430
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
Definition: wallet.h:401
RecursiveMutex cs_wallet
Definition: wallet.h:389
bool IsLegacy() const
Determine if we are a legacy wallet.
Definition: wallet.cpp:3427
interfaces::Chain & chain() const
Interface for accessing chain state.
Definition: wallet.h:448
int GetLastBlockHeight() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get last block processed height.
Definition: wallet.h:1021
OutputType m_default_address_type
Definition: wallet.h:739
int64_t ScanningDuration() const
Definition: wallet.h:517
LegacyScriptPubKeyMan * GetLegacyScriptPubKeyMan() const
Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
Definition: wallet.cpp:3271
CFeeRate m_pay_tx_fee
Definition: wallet.h:725
bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
check whether we are allowed to upgrade (or already support) to the named feature
Definition: wallet.h:486
bool IsScanning() const
Definition: wallet.h:516
CFeeRate m_min_fee
Definition: wallet.h:730
int GetVersion() const
get the current wallet format (the oldest client version guaranteed to understand this wallet)
Definition: wallet.h:815
Amount m_default_max_tx_fee
Absolute maximum transaction fee (in satoshis) used by default for the wallet.
Definition: wallet.h:751
bool UpgradeWallet(int version, bilingual_str &error)
Upgrade the wallet.
Definition: wallet.cpp:3043
ScriptPubKeyMan * GetScriptPubKeyMan(const OutputType &type, bool internal) const
Get the ScriptPubKeyMan for the given OutputType and internal/external chain.
Definition: wallet.cpp:3210
bool IsCrypted() const
Definition: wallet.cpp:3143
std::multimap< int64_t, CWalletTx * > TxItems
Definition: wallet.h:429
std::optional< OutputType > m_default_change_type
Default output type for change outputs.
Definition: wallet.h:746
const CAddressBookData * FindAddressBookEntry(const CTxDestination &, bool allow_change=false) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:3031
A transaction with a bunch of additional info that only the owner cares about.
Definition: transaction.h:65
CTransactionRef tx
Definition: transaction.h:160
TxId GetId() const
Definition: transaction.h:300
bool IsCoinBase() const
Definition: transaction.h:301
Definition: config.h:19
const SigningProvider *const provider
Definition: rpcwallet.cpp:3831
UniValue operator()(const PKHash &pkhash) const
Definition: rpcwallet.cpp:3878
UniValue operator()(const ScriptHash &scripthash) const
Definition: rpcwallet.cpp:3889
void ProcessSubScript(const CScript &subscript, UniValue &obj) const
Definition: rpcwallet.cpp:3833
DescribeWalletAddressVisitor(const SigningProvider *_provider)
Definition: rpcwallet.cpp:3871
UniValue operator()(const CNoDestination &dest) const
Definition: rpcwallet.cpp:3874
Fast randomness source.
Definition: random.h:156
RecursiveMutex cs_KeyStore
const CHDChain & GetHDChain() const
void SetHDSeed(const CPubKey &key)
bool NewKeyPool()
Mark old keypool keys as used, and generate all new keys.
CPubKey DeriveNewSeed(const CKey &key)
A class implementing ScriptPubKeyMan manages some (or all) scriptPubKeys used in a wallet.
virtual std::unique_ptr< CKeyMetadata > GetMetadata(const CTxDestination &dest) const
Signature hash type wrapper class.
Definition: sighashtype.h:37
bool hasForkId() const
Definition: sighashtype.h:77
An interface to be implemented by keystores that support signing.
virtual bool GetCScript(const CScriptID &scriptid, CScript &script) const
virtual bool GetPubKey(const CKeyID &address, CPubKey &pubkey) const
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:93
const std::string & get_str() const
const UniValue & find_value(std::string_view key) const
Definition: univalue.cpp:234
@ VNULL
Definition: univalue.h:27
@ VOBJ
Definition: univalue.h:27
@ VSTR
Definition: univalue.h:27
@ VARR
Definition: univalue.h:27
@ VNUM
Definition: univalue.h:27
@ VBOOL
Definition: univalue.h:27
int64_t get_int64() const
bool isNull() const
Definition: univalue.h:89
const UniValue & get_obj() const
void __pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:127
size_t size() const
Definition: univalue.h:80
enum VType type() const
Definition: univalue.h:135
const std::vector< UniValue > & getValues() const
const std::vector< std::string > & getKeys() const
bool empty() const
Definition: univalue.h:78
bool pushKVs(const UniValue &obj)
Definition: univalue.cpp:146
bool push_back(const UniValue &val)
Definition: univalue.cpp:108
const UniValue & get_array() const
bool exists(const std::string &key) const
Definition: univalue.h:87
void reserve(size_t n)
Definition: univalue.h:55
bool pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:133
bool get_bool() const
int get_int() const
RAII object to check and reserve a wallet rescan.
Definition: wallet.h:1099
bool IsNull() const
Definition: uint256.h:32
std::string GetHex() const
Definition: uint256.cpp:16
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
Definition: chain.h:123
virtual int rpcSerializationFlags()=0
Current RPC serialization flags.
virtual bool findBlock(const BlockHash &hash, const FoundBlock &block={})=0
Return whether node has the block and optionally return block metadata or contents.
virtual void findCoins(std::map< COutPoint, Coin > &coins)=0
Look up unspent output information.
virtual bool hasBlocks(const BlockHash &block_hash, int min_height=0, std::optional< int > max_height={})=0
Return true if data is available for all blocks in the specified range of blocks.
virtual bool findAncestorByHeight(const BlockHash &block_hash, int ancestor_height, const FoundBlock &ancestor_out={})=0
Find ancestor of block at specified height and optionally return ancestor information.
virtual CFeeRate relayMinFee()=0
Relay current minimum fee (from -minrelaytxfee settings).
virtual const CChainParams & params() const =0
This Chain's parameters.
Helper for findBlock to selectively return pieces of block data.
Definition: chain.h:48
256-bit opaque blob.
Definition: uint256.h:129
const Config & GetConfig()
Definition: config.cpp:40
void TxToUniv(const CTransaction &tx, const BlockHash &hashBlock, UniValue &entry, bool include_hex=true, int serialize_flags=0, const CTxUndo *txundo=nullptr)
Definition: core_write.cpp:217
bool DecodeHexTx(CMutableTransaction &tx, const std::string &strHexTx)
Definition: core_read.cpp:197
std::string EncodeHexTx(const CTransaction &tx, const int serializeFlags=0)
Definition: core_write.cpp:169
SigHashType ParseSighashString(const UniValue &sighash)
Definition: core_read.cpp:271
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible.
TransactionError
Definition: error.h:22
void LockCoin(const COutPoint &output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2455
size_t KeypoolCountExternalKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2301
void CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector< std::pair< std::string, std::string >> orderForm, bool broadcast=true)
Add the transaction to the wallet and maybe attempt to broadcast it.
Definition: wallet.cpp:2124
void ListLockedCoins(std::vector< COutPoint > &vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2476
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2312
bool IsLockedCoin(const COutPoint &outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2470
void UnlockCoin(const COutPoint &output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2460
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::string &purpose)
Definition: wallet.cpp:2260
bool SignTransaction(CMutableTransaction &tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2003
bool GetNewChangeDestination(const OutputType type, CTxDestination &dest, std::string &error)
Definition: wallet.cpp:2351
void UnlockAllCoins() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2465
bool TopUpKeyPool(unsigned int kpSize=0)
Definition: wallet.cpp:2322
TransactionError FillPSBT(PartiallySignedTransaction &psbtx, bool &complete, SigHashType sighash_type=SigHashType().withForkId(), bool sign=true, bool bip32derivs=true) const
Fills out a PSBT with information from the wallet.
Definition: wallet.cpp:2050
int64_t GetOldestKeyPoolTime() const
Definition: wallet.cpp:2368
bool GetNewDestination(const OutputType type, const std::string label, CTxDestination &dest, std::string &error)
Definition: wallet.cpp:2331
isminetype IsMine(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:1424
bool CanGetAddresses(bool internal=false) const
Returns true if the wallet can give out new addresses.
Definition: wallet.cpp:1476
ScanResult ScanForWalletTransactions(const BlockHash &start_block, int start_height, std::optional< int > max_height, const WalletRescanReserver &reserver, bool fUpdate)
Scan the block chain (starting in start_block) for transactions from or to us.
Definition: wallet.cpp:1707
bool IsSpentKey(const TxId &txid, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:925
const CChainParams & GetChainParams() const override
Definition: wallet.cpp:386
bool IsSpent(const COutPoint &outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Outpoint is spent if any non-conflicted transaction, spends it:
Definition: wallet.cpp:661
void UnsetWalletFlag(uint64_t flag)
Unsets a single wallet flag.
Definition: wallet.cpp:1499
bool IsWalletFlagSet(uint64_t flag) const override
Check if a certain wallet flag is set.
Definition: wallet.cpp:1517
bool AbandonTransaction(const TxId &txid)
Mark a transaction (and it in-wallet descendants) as abandoned so its inputs may be respent.
Definition: wallet.cpp:1170
uint8_t isminefilter
Definition: wallet.h:41
isminetype
IsMine() return codes.
Definition: ismine.h:18
@ ISMINE_SPENDABLE
Definition: ismine.h:21
@ ISMINE_WATCH_ONLY
Definition: ismine.h:20
std::string EncodeDestination(const CTxDestination &dest, const Config &config)
Definition: key_io.cpp:167
bool IsValidDestinationString(const std::string &str, const CChainParams &params)
Definition: key_io.cpp:183
CTxDestination DecodeDestination(const std::string &addr, const CChainParams &params)
Definition: key_io.cpp:174
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:77
bool error(const char *fmt, const Args &...args)
Definition: logging.h:225
std::string FormatMoney(const Amount amt)
Do not use these functions to represent or parse monetary amounts to or from JSON but use AmountFromV...
Definition: moneystr.cpp:13
static bool isNull(const AnyVoteItem &item)
Definition: processor.cpp:406
bool ParseOutputType(const std::string &type, OutputType &output_type)
Definition: outputtype.cpp:19
OutputType
Definition: outputtype.h:16
static CTransactionRef MakeTransactionRef()
Definition: transaction.h:316
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:315
Response response
Definition: processor.cpp:491
bool DecodeBase64PSBT(PartiallySignedTransaction &psbt, const std::string &base64_tx, std::string &error)
Decode a base64ed PSBT into a PartiallySignedTransaction.
Definition: psbt.cpp:296
bool FinalizeAndExtractPSBT(PartiallySignedTransaction &psbtx, CMutableTransaction &result)
Finalizes a PSBT if possible, and extracts it to a CMutableTransaction if it could be finalized.
Definition: psbt.cpp:247
void SignTransactionResultToJSON(CMutableTransaction &mtx, bool complete, const std::map< COutPoint, Coin > &coins, const std::map< int, std::string > &input_errors, UniValue &result)
CMutableTransaction ConstructTransaction(const CChainParams &params, const UniValue &inputs_in, const UniValue &outputs_in, const UniValue &locktime)
Create a transaction from univalue parameters.
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.
std::set< std::set< CTxDestination > > GetAddressGroupings(const CWallet &wallet)
Definition: receive.cpp:453
bool CachedTxIsFromMe(const CWallet &wallet, const CWalletTx &wtx, const isminefilter &filter)
Definition: receive.cpp:321
Amount CachedTxGetDebit(const CWallet &wallet, const CWalletTx &wtx, const isminefilter &filter)
filter decides which addresses will count towards the debit
Definition: receive.cpp:164
bool ScriptIsChange(const CWallet &wallet, const CScript &script)
Definition: receive.cpp:75
std::map< CTxDestination, Amount > GetAddressBalances(const CWallet &wallet)
Definition: receive.cpp:413
void CachedTxGetAmounts(const CWallet &wallet, const CWalletTx &wtx, std::list< COutputEntry > &listReceived, std::list< COutputEntry > &listSent, Amount &nFee, const isminefilter &filter)
Definition: receive.cpp:262
Amount CachedTxGetCredit(const CWallet &wallet, const CWalletTx &wtx, const isminefilter &filter)
Definition: receive.cpp:139
bool CachedTxIsTrusted(const CWallet &wallet, const CWalletTx &wtx, std::set< TxId > &trusted_parents)
Definition: receive.cpp:326
Balance GetBalance(const CWallet &wallet, const int min_depth, bool avoid_reuse)
Definition: receive.cpp:384
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:58
const char * name
Definition: rest.cpp:47
RPCErrorCode
Bitcoin RPC error codes.
Definition: protocol.h:22
@ RPC_WALLET_INVALID_LABEL_NAME
Invalid label name.
Definition: protocol.h:94
@ RPC_MISC_ERROR
General application defined errors std::exception thrown in command handling.
Definition: protocol.h:38
@ RPC_WALLET_INSUFFICIENT_FUNDS
Not enough funds in wallet or account.
Definition: protocol.h:92
@ RPC_WALLET_ENCRYPTION_FAILED
Failed to encrypt the wallet.
Definition: protocol.h:105
@ RPC_METHOD_DEPRECATED
RPC method is deprecated.
Definition: protocol.h:60
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
Definition: protocol.h:46
@ RPC_WALLET_ERROR
Wallet errors Unspecified problem with wallet (key not found etc.)
Definition: protocol.h:90
@ RPC_WALLET_NOT_FOUND
Invalid wallet specified.
Definition: protocol.h:109
@ RPC_INTERNAL_ERROR
Definition: protocol.h:33
@ RPC_WALLET_KEYPOOL_RAN_OUT
Keypool ran out, call keypoolrefill first.
Definition: protocol.h:96
@ RPC_DESERIALIZATION_ERROR
Error parsing or validating structure in raw format.
Definition: protocol.h:50
@ RPC_INVALID_ADDRESS_OR_KEY
Invalid address or key.
Definition: protocol.h:42
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:160
CTxDestination AddAndGetMultisigDestination(const int required, const std::vector< CPubKey > &pubkeys, OutputType type, FillableSigningProvider &keystore, CScript &script_out)
Definition: util.cpp:243
std::string HelpExampleRpcNamed(const std::string &methodname, const RPCArgList &args)
Definition: util.cpp:186
void RPCTypeCheckArgument(const UniValue &value, const UniValueType &typeExpected)
Type-check one argument; throws JSONRPCError if wrong type given.
Definition: util.cpp:26
UniValue JSONRPCTransactionError(TransactionError terr, const std::string &err_string)
Definition: util.cpp:343
Amount AmountFromValue(const UniValue &value)
Definition: util.cpp:65
const std::string EXAMPLE_ADDRESS
Example CashAddr address used in multiple RPCExamples.
Definition: util.cpp:23
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:177
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:22
CPubKey HexToPubKey(const std::string &hex_in)
Definition: util.cpp:201
CPubKey AddrToPubKey(const CChainParams &chainparams, const FillableSigningProvider &keystore, const std::string &addr_in)
Definition: util.cpp:215
uint256 ParseHashO(const UniValue &o, std::string strKey)
Definition: util.cpp:100
uint256 ParseHashV(const UniValue &v, std::string strName)
Utilities: convert hex-encoded values (throws error if not hex).
Definition: util.cpp:83
void RPCTypeCheckObj(const UniValue &o, const std::map< std::string, UniValueType > &typesExpected, bool fAllowNull, bool fStrict)
Check for expected keys/value types in an Object.
Definition: util.cpp:36
std::string HelpExampleCliNamed(const std::string &methodname, const RPCArgList &args)
Definition: util.cpp:165
UniValue DescribeAddress(const CTxDestination &dest)
Definition: util.cpp:311
static RPCHelpMan createwallet()
Definition: rpcwallet.cpp:2805
static RPCHelpMan getnewaddress()
Definition: rpcwallet.cpp:95
static RPCHelpMan sethdseed()
Definition: rpcwallet.cpp:4472
static RPCHelpMan listreceivedbylabel()
Definition: rpcwallet.cpp:1216
static RPCHelpMan sendtoaddress()
Definition: rpcwallet.cpp:316
static RPCHelpMan listunspent()
Definition: rpcwallet.cpp:2985
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)
List transactions based on the given criteria.
Definition: rpcwallet.cpp:1295
static RPCHelpMan getrawchangeaddress()
Definition: rpcwallet.cpp:159
RPCHelpMan listlabels()
Definition: rpcwallet.cpp:4165
static RPCHelpMan walletprocesspsbt()
Definition: rpcwallet.cpp:4571
static RPCHelpMan fundrawtransaction()
Definition: rpcwallet.cpp:3445
static RPCHelpMan gettransaction()
Definition: rpcwallet.cpp:1809
static UniValue ListReceived(const Config &config, const CWallet *const pwallet, const UniValue &params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
Definition: rpcwallet.cpp:984
static UniValue AddressBookDataToJSON(const CAddressBookData &data, const bool verbose)
Convert CAddressBookData to JSON record.
Definition: rpcwallet.cpp:3915
static RPCHelpMan listaddressgroupings()
Definition: rpcwallet.cpp:418
static void WalletTxToJSON(const CWallet &wallet, const CWalletTx &wtx, UniValue &entry) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
Definition: rpcwallet.cpp:60
static RPCHelpMan addmultisigaddress()
Definition: rpcwallet.cpp:870
RPCHelpMan getaddressesbylabel()
Definition: rpcwallet.cpp:4096
static RPCHelpMan listlockunspent()
Definition: rpcwallet.cpp:2256
static RPCHelpMan send()
Definition: rpcwallet.cpp:4227
static Amount GetReceived(const CWallet &wallet, const UniValue &params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
Definition: rpcwallet.cpp:490
static RPCHelpMan getunconfirmedbalance()
Definition: rpcwallet.cpp:711
static RPCHelpMan listwallets()
Definition: rpcwallet.cpp:2649
RPCHelpMan rescanblockchain()
Definition: rpcwallet.cpp:3719
static RPCHelpMan upgradewallet()
Definition: rpcwallet.cpp:4851
static RPCHelpMan unloadwallet()
Definition: rpcwallet.cpp:2918
static RPCHelpMan walletcreatefundedpsbt()
Definition: rpcwallet.cpp:4654
static RPCHelpMan getbalances()
Definition: rpcwallet.cpp:2377
static RPCHelpMan listwalletdir()
Definition: rpcwallet.cpp:2609
static RPCHelpMan keypoolrefill()
Definition: rpcwallet.cpp:2032
bool HaveKey(const SigningProvider &wallet, const CKey &key)
Checks if a CKey is in the given CWallet compressed or otherwise.
Definition: rpcwallet.cpp:53
RPCHelpMan getaddressinfo()
Definition: rpcwallet.cpp:3925
static RPCHelpMan getwalletinfo()
Definition: rpcwallet.cpp:2472
static RPCHelpMan lockunspent()
Definition: rpcwallet.cpp:2086
Span< const CRPCCommand > GetWalletRPCCommands()
Definition: rpcwallet.cpp:4940
UniValue SendMoney(CWallet *const pwallet, const CCoinControl &coin_control, std::vector< CRecipient > &recipients, mapValue_t map_value, bool broadcast=true)
Definition: rpcwallet.cpp:291
static RPCHelpMan setwalletflag()
Definition: rpcwallet.cpp:2721
RPCHelpMan signrawtransactionwithwallet()
Definition: rpcwallet.cpp:3588
static RPCHelpMan createwallettransaction()
Definition: rpcwallet.cpp:4890
static RPCHelpMan setlabel()
Definition: rpcwallet.cpp:205
RPCHelpMan signmessage()
Definition: signmessage.cpp:13
static RPCHelpMan getreceivedbyaddress()
Definition: rpcwallet.cpp:540
static RPCHelpMan getreceivedbylabel()
Definition: rpcwallet.cpp:590
static void MaybePushAddress(UniValue &entry, const CTxDestination &dest)
Definition: rpcwallet.cpp:1277
static RPCHelpMan getbalance()
Definition: rpcwallet.cpp:636
static const std::vector< RPCResult > TransactionDescriptionString()
Definition: rpcwallet.cpp:1378
static RPCHelpMan loadwallet()
Definition: rpcwallet.cpp:2677
static RPCHelpMan listsinceblock()
Definition: rpcwallet.cpp:1574
static RPCHelpMan settxfee()
Definition: rpcwallet.cpp:2323
static RPCHelpMan listreceivedbyaddress()
Definition: rpcwallet.cpp:1138
static RPCHelpMan sendmany()
Definition: rpcwallet.cpp:739
RPCHelpMan listtransactions()
Definition: rpcwallet.cpp:1414
static UniValue DescribeWalletAddress(const CWallet *const pwallet, const CTxDestination &dest)
Definition: rpcwallet.cpp:3900
void ParseRecipients(const UniValue &address_amounts, const UniValue &subtract_fee_outputs, std::vector< CRecipient > &recipients, const CChainParams &chainParams)
Definition: rpcwallet.cpp:253
void FundTransaction(CWallet *const pwallet, CMutableTransaction &tx, Amount &fee_out, int &change_position, const UniValue &options, CCoinControl &coinControl)
Definition: rpcwallet.cpp:3289
static RPCHelpMan abandontransaction()
Definition: rpcwallet.cpp:1977
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition: secure.h:55
@ SER_NETWORK
Definition: serialize.h:152
bool IsSolvable(const SigningProvider &provider, const CScript &script)
Check whether we know how to sign for an output like this, assuming we have all private keys.
Definition: sign.cpp:424
bool CreateTransaction(CWallet &wallet, const std::vector< CRecipient > &vecSend, CTransactionRef &tx, Amount &nFeeRet, int &nChangePosInOut, bilingual_str &error, const CCoinControl &coin_control, bool sign)
Create a new transaction paying the recipients with a set of coins selected by SelectCoins(); Also cr...
Definition: spend.cpp:993
void AvailableCoins(const CWallet &wallet, std::vector< COutput > &vCoins, const CCoinControl *coinControl, const Amount nMinimumAmount, const Amount nMaximumAmount, const Amount nMinimumSumAmount, const uint64_t nMaximumCount)
populate vCoins with vector of available COutputs.
Definition: spend.cpp:73
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:158
std::string GetTxnOutputType(TxoutType t)
Get the name of a TxoutType as a string.
Definition: standard.cpp:29
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< uint8_t >> &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
Definition: standard.cpp:108
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:260
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Definition: standard.cpp:240
CKeyID ToKeyID(const PKHash &key_hash)
Definition: standard.cpp:25
TxoutType
Definition: standard.h:38
std::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:85
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
std::string EncodeBase64(Span< const uint8_t > input)
bool IsHex(const std::string &str)
Returns true if each character in str is a hex character, and has an even number of hex digits.
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:54
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:87
Definition: amount.h:19
static constexpr Amount zero() noexcept
Definition: amount.h:32
Amount m_mine_untrusted_pending
Untrusted, but in mempool (pending)
Definition: receive.h:73
A BlockHash is a unqiue identifier for a block.
Definition: blockhash.h:13
Definition: receive.h:53
std::optional< int > last_scanned_height
Definition: wallet.h:618
enum CWallet::ScanResult::@20 status
static const Currency & get()
Definition: amount.cpp:18
std::string ticker
Definition: amount.h:150
bool require_create
Definition: db.h:223
uint64_t create_flags
Definition: db.h:224
SecureString create_passphrase
Definition: db.h:225
A version of CTransaction with the PSBT format.
Definition: psbt.h:334
@ STR_HEX
Special type that is a STR with only hex chars.
@ AMOUNT
Special type representing a floating point amount (can be either NUM or STR)
std::string DefaultHint
Definition: util.h:181
@ OMITTED_NAMED_ARG
Optional arg that is a named argument and has a default value of null.
@ OMITTED
Optional argument with default value omitted because they are implicitly clear.
@ NO
Required arg.
std::string oneline_description
Should be empty unless it is supposed to override the auto-generated summary line.
Definition: util.h:134
bool skip_type_check
Definition: util.h:131
@ ELISION
Special type to denote elision (...)
@ NUM_TIME
Special numeric to denote unix epoch time.
@ ARR_FIXED
Special array that has a fixed number of entries.
@ OBJ_DYN
Special dictionary with keys that are not literals.
@ STR_HEX
Special string with only hex chars.
@ STR_AMOUNT
Special string to represent a floating point amount.
A TxId is the identifier of a transaction.
Definition: txid.h:14
Wrapper for UniValue::VType, which includes typeAny: used to denote don't care type.
Definition: util.h:46
WalletContext struct containing references to state shared between CWallet instances,...
Definition: context.h:23
interfaces::Chain * chain
Definition: context.h:24
Bilingual messages:
Definition: translation.h:17
std::vector< uint256 > txids
Definition: rpcwallet.cpp:979
Amount nAmount
Definition: rpcwallet.cpp:977
bool fIsWatchonly
Definition: rpcwallet.cpp:980
#define LOCK2(cs1, cs2)
Definition: sync.h:309
#define LOCK(cs)
Definition: sync.h:306
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:56
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1202
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition: translation.h:36
const UniValue NullUniValue
Definition: univalue.cpp:13
V Cat(V v1, V &&v2)
Concatenate two vectors, moving elements.
Definition: vector.h:32
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:11
DatabaseStatus
Definition: db.h:229
void EnsureWalletIsUnlocked(const CWallet *pwallet)
Definition: util.cpp:94
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: util.cpp:63
LegacyScriptPubKeyMan & EnsureLegacyScriptPubKeyMan(CWallet &wallet, bool also_create)
Definition: util.cpp:112
WalletContext & EnsureWalletContext(const std::any &context)
Definition: util.cpp:102
bool GetAvoidReuseFlag(const CWallet *const pwallet, const UniValue &param)
Definition: util.cpp:21
std::tuple< std::shared_ptr< CWallet >, std::vector< bilingual_str > > LoadWalletHelper(WalletContext &context, UniValue load_on_start_param, const std::string wallet_name)
Definition: util.cpp:134
bool ParseIncludeWatchonly(const UniValue &include_watchonly, const CWallet &pwallet)
Used by RPC commands that have an include_watchonly parameter.
Definition: util.cpp:38
const std::string HELP_REQUIRING_PASSPHRASE
Definition: util.cpp:17
std::string LabelFromValue(const UniValue &value)
Definition: util.cpp:125
bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest &request, std::string &wallet_name)
Definition: util.cpp:50
std::map< std::string, std::string > mapValue_t
Definition: transaction.h:21
static constexpr uint64_t MUTABLE_WALLET_FLAGS
Definition: wallet.h:133
static const std::map< std::string, WalletFlags > WALLET_FLAG_MAP
Definition: wallet.h:135
bool RemoveWallet(const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:121
const std::map< uint64_t, std::string > WALLET_FLAG_CAVEATS
Definition: wallet.cpp:44
std::shared_ptr< CWallet > GetWallet(const std::string &name)
Definition: wallet.cpp:156
std::shared_ptr< CWallet > CreateWallet(interfaces::Chain &chain, const std::string &name, std::optional< bool > load_on_start, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:283
void UnloadWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly unload and delete the wallet.
Definition: wallet.cpp:202
std::vector< std::shared_ptr< CWallet > > GetWallets()
Definition: wallet.cpp:151
std::vector< fs::path > ListWalletDir()
Get wallets in wallet directory.
Definition: walletutil.cpp:70
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
Definition: walletutil.h:55
@ WALLET_FLAG_AVOID_REUSE
Definition: walletutil.h:47
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
Definition: walletutil.h:70
@ WALLET_FLAG_BLANK_WALLET
Flag set when a wallet contains no HD seed and no private keys, scripts, addresses,...
Definition: walletutil.h:67
@ FEATURE_HD_SPLIT
Definition: walletutil.h:28
@ FEATURE_HD
Definition: walletutil.h:25
@ FEATURE_LATEST
Definition: walletutil.h:36