Bitcoin ABC  0.26.3
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].getInt<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].getInt<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].getInt<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].getInt<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 template <class Vec>
1296 static void ListTransactions(const CWallet *const pwallet, const CWalletTx &wtx,
1297  int nMinDepth, bool fLong, Vec &ret,
1298  const isminefilter &filter_ismine,
1299  const std::string *filter_label)
1300  EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) {
1301  Amount nFee;
1302  std::list<COutputEntry> listReceived;
1303  std::list<COutputEntry> listSent;
1304 
1305  CachedTxGetAmounts(*pwallet, wtx, listReceived, listSent, nFee,
1306  filter_ismine);
1307 
1308  bool involvesWatchonly = CachedTxIsFromMe(*pwallet, wtx, ISMINE_WATCH_ONLY);
1309 
1310  // Sent
1311  if (!filter_label) {
1312  for (const COutputEntry &s : listSent) {
1313  UniValue entry(UniValue::VOBJ);
1314  if (involvesWatchonly ||
1315  (pwallet->IsMine(s.destination) & ISMINE_WATCH_ONLY)) {
1316  entry.pushKV("involvesWatchonly", true);
1317  }
1318  MaybePushAddress(entry, s.destination);
1319  entry.pushKV("category", "send");
1320  entry.pushKV("amount", -s.amount);
1321  const auto *address_book_entry =
1322  pwallet->FindAddressBookEntry(s.destination);
1323  if (address_book_entry) {
1324  entry.pushKV("label", address_book_entry->GetLabel());
1325  }
1326  entry.pushKV("vout", s.vout);
1327  entry.pushKV("fee", -1 * nFee);
1328  if (fLong) {
1329  WalletTxToJSON(*pwallet, wtx, entry);
1330  }
1331  entry.pushKV("abandoned", wtx.isAbandoned());
1332  ret.push_back(entry);
1333  }
1334  }
1335 
1336  // Received
1337  if (listReceived.size() > 0 &&
1338  pwallet->GetTxDepthInMainChain(wtx) >= nMinDepth) {
1339  for (const COutputEntry &r : listReceived) {
1340  std::string label;
1341  const auto *address_book_entry =
1342  pwallet->FindAddressBookEntry(r.destination);
1343  if (address_book_entry) {
1344  label = address_book_entry->GetLabel();
1345  }
1346  if (filter_label && label != *filter_label) {
1347  continue;
1348  }
1349  UniValue entry(UniValue::VOBJ);
1350  if (involvesWatchonly ||
1351  (pwallet->IsMine(r.destination) & ISMINE_WATCH_ONLY)) {
1352  entry.pushKV("involvesWatchonly", true);
1353  }
1354  MaybePushAddress(entry, r.destination);
1355  if (wtx.IsCoinBase()) {
1356  if (pwallet->GetTxDepthInMainChain(wtx) < 1) {
1357  entry.pushKV("category", "orphan");
1358  } else if (pwallet->IsTxImmatureCoinBase(wtx)) {
1359  entry.pushKV("category", "immature");
1360  } else {
1361  entry.pushKV("category", "generate");
1362  }
1363  } else {
1364  entry.pushKV("category", "receive");
1365  }
1366  entry.pushKV("amount", r.amount);
1367  if (address_book_entry) {
1368  entry.pushKV("label", label);
1369  }
1370  entry.pushKV("vout", r.vout);
1371  if (fLong) {
1372  WalletTxToJSON(*pwallet, wtx, entry);
1373  }
1374  ret.push_back(entry);
1375  }
1376  }
1377 }
1378 
1379 static const std::vector<RPCResult> TransactionDescriptionString() {
1380  return {
1381  {RPCResult::Type::NUM, "confirmations",
1382  "The number of confirmations for the transaction. Negative "
1383  "confirmations means the\n"
1384  "transaction conflicted that many blocks ago."},
1385  {RPCResult::Type::BOOL, "generated",
1386  "Only present if transaction only input is a coinbase one."},
1387  {RPCResult::Type::BOOL, "trusted",
1388  "Only present if we consider transaction to be trusted and so safe to "
1389  "spend from."},
1390  {RPCResult::Type::STR_HEX, "blockhash",
1391  "The block hash containing the transaction."},
1392  {RPCResult::Type::NUM, "blockheight",
1393  "The block height containing the transaction."},
1394  {RPCResult::Type::NUM, "blockindex",
1395  "The index of the transaction in the block that includes it."},
1396  {RPCResult::Type::NUM_TIME, "blocktime",
1397  "The block time expressed in " + UNIX_EPOCH_TIME + "."},
1398  {RPCResult::Type::STR_HEX, "txid", "The transaction id."},
1400  "walletconflicts",
1401  "Conflicting transaction ids.",
1402  {
1403  {RPCResult::Type::STR_HEX, "txid", "The transaction id."},
1404  }},
1405  {RPCResult::Type::NUM_TIME, "time",
1406  "The transaction time expressed in " + UNIX_EPOCH_TIME + "."},
1407  {RPCResult::Type::NUM_TIME, "timereceived",
1408  "The time received expressed in " + UNIX_EPOCH_TIME + "."},
1409  {RPCResult::Type::STR, "comment",
1410  "If a comment is associated with the transaction, only present if not "
1411  "empty."},
1412  };
1413 }
1414 
1416  const auto &ticker = Currency::get().ticker;
1417  return RPCHelpMan{
1418  "listtransactions",
1419  "If a label name is provided, this will return only incoming "
1420  "transactions paying to addresses with the specified label.\n"
1421  "\nReturns up to 'count' most recent transactions skipping the first "
1422  "'from' transactions.\n",
1423  {
1424  {"label|dummy", RPCArg::Type::STR,
1426  "If set, should be a valid label name to return only incoming "
1427  "transactions with the specified label, or \"*\" to disable "
1428  "filtering and return all transactions."},
1429  {"count", RPCArg::Type::NUM, RPCArg::Default{10},
1430  "The number of transactions to return"},
1431  {"skip", RPCArg::Type::NUM, RPCArg::Default{0},
1432  "The number of transactions to skip"},
1433  {"include_watchonly", RPCArg::Type::BOOL,
1435  "true for watch-only wallets, otherwise false"},
1436  "Include transactions to watch-only addresses (see "
1437  "'importaddress')"},
1438  },
1439  RPCResult{
1441  "",
1442  "",
1443  {
1444  {RPCResult::Type::OBJ, "", "",
1445  Cat(Cat<std::vector<RPCResult>>(
1446  {
1447  {RPCResult::Type::BOOL, "involvesWatchonly",
1448  "Only returns true if imported addresses were "
1449  "involved in transaction."},
1450  {RPCResult::Type::STR, "address",
1451  "The bitcoin address of the transaction."},
1452  {RPCResult::Type::STR, "category",
1453  "The transaction category.\n"
1454  "\"send\" Transactions sent.\n"
1455  "\"receive\" Non-coinbase "
1456  "transactions received.\n"
1457  "\"generate\" Coinbase transactions "
1458  "received with more than 100 confirmations.\n"
1459  "\"immature\" Coinbase transactions "
1460  "received with 100 or fewer confirmations.\n"
1461  "\"orphan\" Orphaned coinbase "
1462  "transactions received."},
1463  {RPCResult::Type::STR_AMOUNT, "amount",
1464  "The amount in " + ticker +
1465  ". This is negative for the 'send' category, "
1466  "and is positive\n"
1467  "for all other categories"},
1468  {RPCResult::Type::STR, "label",
1469  "A comment for the address/transaction, if any"},
1470  {RPCResult::Type::NUM, "vout", "the vout value"},
1472  "The amount of the fee in " + ticker +
1473  ". This is negative and only available for "
1474  "the\n"
1475  "'send' category of transactions."},
1476  },
1478  {
1479  {RPCResult::Type::BOOL, "abandoned",
1480  "'true' if the transaction has been abandoned "
1481  "(inputs are respendable). Only available for the \n"
1482  "'send' category of transactions."},
1483  })},
1484  }},
1485  RPCExamples{"\nList the most recent 10 transactions in the systems\n" +
1486  HelpExampleCli("listtransactions", "") +
1487  "\nList transactions 100 to 120\n" +
1488  HelpExampleCli("listtransactions", "\"*\" 20 100") +
1489  "\nAs a JSON-RPC call\n" +
1490  HelpExampleRpc("listtransactions", "\"*\", 20, 100")},
1491  [&](const RPCHelpMan &self, const Config &config,
1492  const JSONRPCRequest &request) -> UniValue {
1493  std::shared_ptr<CWallet> const wallet =
1494  GetWalletForJSONRPCRequest(request);
1495  if (!wallet) {
1496  return NullUniValue;
1497  }
1498  const CWallet *const pwallet = wallet.get();
1499 
1500  // Make sure the results are valid at least up to the most recent
1501  // block the user could have gotten from another RPC command prior
1502  // to now
1503  pwallet->BlockUntilSyncedToCurrentChain();
1504 
1505  const std::string *filter_label = nullptr;
1506  if (!request.params[0].isNull() &&
1507  request.params[0].get_str() != "*") {
1508  filter_label = &request.params[0].get_str();
1509  if (filter_label->empty()) {
1510  throw JSONRPCError(
1512  "Label argument must be a valid label name or \"*\".");
1513  }
1514  }
1515  int nCount = 10;
1516  if (!request.params[1].isNull()) {
1517  nCount = request.params[1].getInt<int>();
1518  }
1519 
1520  int nFrom = 0;
1521  if (!request.params[2].isNull()) {
1522  nFrom = request.params[2].getInt<int>();
1523  }
1524 
1525  isminefilter filter = ISMINE_SPENDABLE;
1526  if (ParseIncludeWatchonly(request.params[3], *pwallet)) {
1527  filter |= ISMINE_WATCH_ONLY;
1528  }
1529 
1530  if (nCount < 0) {
1531  throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
1532  }
1533  if (nFrom < 0) {
1534  throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
1535  }
1536 
1537  std::vector<UniValue> ret;
1538  {
1539  LOCK(pwallet->cs_wallet);
1540 
1541  const CWallet::TxItems &txOrdered = pwallet->wtxOrdered;
1542 
1543  // iterate backwards until we have nCount items to return:
1544  for (CWallet::TxItems::const_reverse_iterator it =
1545  txOrdered.rbegin();
1546  it != txOrdered.rend(); ++it) {
1547  CWalletTx *const pwtx = (*it).second;
1548  ListTransactions(pwallet, *pwtx, 0, true, ret, filter,
1549  filter_label);
1550  if (int(ret.size()) >= (nCount + nFrom)) {
1551  break;
1552  }
1553  }
1554  }
1555 
1556  // ret is newest to oldest
1557 
1558  if (nFrom > (int)ret.size()) {
1559  nFrom = ret.size();
1560  }
1561  if ((nFrom + nCount) > (int)ret.size()) {
1562  nCount = ret.size() - nFrom;
1563  }
1564 
1565  auto txs_rev_it{std::make_move_iterator(ret.rend())};
1566  UniValue result{UniValue::VARR};
1567  // Return oldest to newest
1568  result.push_backV(txs_rev_it - nFrom - nCount, txs_rev_it - 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].getInt<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].getInt<int>() < 0) {
2066  throw JSONRPCError(
2068  "Invalid parameter, expected valid size.");
2069  }
2070  kpSize = (unsigned int)request.params[0].getInt<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  bool fUnlock = request.params[0].get_bool();
2170 
2171  if (request.params[1].isNull()) {
2172  if (fUnlock) {
2173  pwallet->UnlockAllCoins();
2174  }
2175  return true;
2176  }
2177 
2178  const UniValue &output_params = request.params[1].get_array();
2179 
2180  // Create and validate the COutPoints first.
2181 
2182  std::vector<COutPoint> outputs;
2183  outputs.reserve(output_params.size());
2184 
2185  for (size_t idx = 0; idx < output_params.size(); idx++) {
2186  const UniValue &o = output_params[idx].get_obj();
2187 
2188  RPCTypeCheckObj(o, {
2189  {"txid", UniValueType(UniValue::VSTR)},
2190  {"vout", UniValueType(UniValue::VNUM)},
2191  });
2192 
2193  const int nOutput = o.find_value("vout").getInt<int>();
2194  if (nOutput < 0) {
2195  throw JSONRPCError(
2197  "Invalid parameter, vout cannot be negative");
2198  }
2199 
2200  const TxId txid(ParseHashO(o, "txid"));
2201  const auto it = pwallet->mapWallet.find(txid);
2202  if (it == pwallet->mapWallet.end()) {
2203  throw JSONRPCError(
2205  "Invalid parameter, unknown transaction");
2206  }
2207 
2208  const COutPoint output(txid, nOutput);
2209  const CWalletTx &trans = it->second;
2210  if (output.GetN() >= trans.tx->vout.size()) {
2211  throw JSONRPCError(
2213  "Invalid parameter, vout index out of bounds");
2214  }
2215 
2216  if (pwallet->IsSpent(output)) {
2217  throw JSONRPCError(
2219  "Invalid parameter, expected unspent output");
2220  }
2221 
2222  const bool is_locked = pwallet->IsLockedCoin(output);
2223  if (fUnlock && !is_locked) {
2224  throw JSONRPCError(
2226  "Invalid parameter, expected locked output");
2227  }
2228 
2229  if (!fUnlock && is_locked) {
2230  throw JSONRPCError(
2232  "Invalid parameter, output already locked");
2233  }
2234 
2235  outputs.push_back(output);
2236  }
2237 
2238  // Atomically set (un)locked status for the outputs.
2239  for (const COutPoint &output : outputs) {
2240  if (fUnlock) {
2241  pwallet->UnlockCoin(output);
2242  } else {
2243  pwallet->LockCoin(output);
2244  }
2245  }
2246 
2247  return true;
2248  },
2249  };
2250 }
2251 
2253  return RPCHelpMan{
2254  "listlockunspent",
2255  "Returns list of temporarily unspendable outputs.\n"
2256  "See the lockunspent call to lock and unlock transactions for "
2257  "spending.\n",
2258  {},
2260  "",
2261  "",
2262  {
2264  "",
2265  "",
2266  {
2267  {RPCResult::Type::STR_HEX, "txid",
2268  "The transaction id locked"},
2269  {RPCResult::Type::NUM, "vout", "The vout value"},
2270  }},
2271  }},
2272  RPCExamples{
2273  "\nList the unspent transactions\n" +
2274  HelpExampleCli("listunspent", "") +
2275  "\nLock an unspent transaction\n" +
2276  HelpExampleCli("lockunspent", "false "
2277  "\"[{\\\"txid\\\":"
2278  "\\\"a08e6907dbbd3d809776dbfc5d82e371"
2279  "b764ed838b5655e72f463568df1aadf0\\\""
2280  ",\\\"vout\\\":1}]\"") +
2281  "\nList the locked transactions\n" +
2282  HelpExampleCli("listlockunspent", "") +
2283  "\nUnlock the transaction again\n" +
2284  HelpExampleCli("lockunspent", "true "
2285  "\"[{\\\"txid\\\":"
2286  "\\\"a08e6907dbbd3d809776dbfc5d82e371"
2287  "b764ed838b5655e72f463568df1aadf0\\\""
2288  ",\\\"vout\\\":1}]\"") +
2289  "\nAs a JSON-RPC call\n" + HelpExampleRpc("listlockunspent", "")},
2290  [&](const RPCHelpMan &self, const Config &config,
2291  const JSONRPCRequest &request) -> UniValue {
2292  std::shared_ptr<CWallet> const wallet =
2293  GetWalletForJSONRPCRequest(request);
2294  if (!wallet) {
2295  return NullUniValue;
2296  }
2297  const CWallet *const pwallet = wallet.get();
2298 
2299  LOCK(pwallet->cs_wallet);
2300 
2301  std::vector<COutPoint> vOutpts;
2302  pwallet->ListLockedCoins(vOutpts);
2303 
2304  UniValue ret(UniValue::VARR);
2305 
2306  for (const COutPoint &output : vOutpts) {
2308 
2309  o.pushKV("txid", output.GetTxId().GetHex());
2310  o.pushKV("vout", int(output.GetN()));
2311  ret.push_back(o);
2312  }
2313 
2314  return ret;
2315  },
2316  };
2317 }
2318 
2320  return RPCHelpMan{
2321  "settxfee",
2322  "Set the transaction fee per kB for this wallet. Overrides the "
2323  "global -paytxfee command line parameter.\n"
2324  "Can be deactivated by passing 0 as the fee. In that case automatic "
2325  "fee selection will be used by default.\n",
2326  {
2328  "The transaction fee in " + Currency::get().ticker + "/kB"},
2329  },
2330  RPCResult{RPCResult::Type::BOOL, "", "Returns true if successful"},
2331  RPCExamples{HelpExampleCli("settxfee", "0.00001") +
2332  HelpExampleRpc("settxfee", "0.00001")},
2333  [&](const RPCHelpMan &self, const Config &config,
2334  const JSONRPCRequest &request) -> UniValue {
2335  std::shared_ptr<CWallet> const wallet =
2336  GetWalletForJSONRPCRequest(request);
2337  if (!wallet) {
2338  return NullUniValue;
2339  }
2340  CWallet *const pwallet = wallet.get();
2341 
2342  LOCK(pwallet->cs_wallet);
2343 
2344  Amount nAmount = AmountFromValue(request.params[0]);
2345  CFeeRate tx_fee_rate(nAmount, 1000);
2346  CFeeRate max_tx_fee_rate(pwallet->m_default_max_tx_fee, 1000);
2347  if (tx_fee_rate == CFeeRate()) {
2348  // automatic selection
2349  } else if (tx_fee_rate < pwallet->chain().relayMinFee()) {
2350  throw JSONRPCError(
2352  strprintf("txfee cannot be less than min relay tx fee (%s)",
2353  pwallet->chain().relayMinFee().ToString()));
2354  } else if (tx_fee_rate < pwallet->m_min_fee) {
2355  throw JSONRPCError(
2357  strprintf("txfee cannot be less than wallet min fee (%s)",
2358  pwallet->m_min_fee.ToString()));
2359  } else if (tx_fee_rate > max_tx_fee_rate) {
2360  throw JSONRPCError(
2362  strprintf(
2363  "txfee cannot be more than wallet max tx fee (%s)",
2364  max_tx_fee_rate.ToString()));
2365  }
2366 
2367  pwallet->m_pay_tx_fee = tx_fee_rate;
2368  return true;
2369  },
2370  };
2371 }
2372 
2374  return RPCHelpMan{
2375  "getbalances",
2376  "Returns an object with all balances in " + Currency::get().ticker +
2377  ".\n",
2378  {},
2380  "",
2381  "",
2382  {
2384  "mine",
2385  "balances from outputs that the wallet can sign",
2386  {
2387  {RPCResult::Type::STR_AMOUNT, "trusted",
2388  "trusted balance (outputs created by the wallet or "
2389  "confirmed outputs)"},
2390  {RPCResult::Type::STR_AMOUNT, "untrusted_pending",
2391  "untrusted pending balance (outputs created by "
2392  "others that are in the mempool)"},
2393  {RPCResult::Type::STR_AMOUNT, "immature",
2394  "balance from immature coinbase outputs"},
2395  {RPCResult::Type::STR_AMOUNT, "used",
2396  "(only present if avoid_reuse is set) balance from "
2397  "coins sent to addresses that were previously "
2398  "spent from (potentially privacy violating)"},
2399  }},
2401  "watchonly",
2402  "watchonly balances (not present if wallet does not "
2403  "watch anything)",
2404  {
2405  {RPCResult::Type::STR_AMOUNT, "trusted",
2406  "trusted balance (outputs created by the wallet or "
2407  "confirmed outputs)"},
2408  {RPCResult::Type::STR_AMOUNT, "untrusted_pending",
2409  "untrusted pending balance (outputs created by "
2410  "others that are in the mempool)"},
2411  {RPCResult::Type::STR_AMOUNT, "immature",
2412  "balance from immature coinbase outputs"},
2413  }},
2414  }},
2415  RPCExamples{HelpExampleCli("getbalances", "") +
2416  HelpExampleRpc("getbalances", "")},
2417  [&](const RPCHelpMan &self, const Config &config,
2418  const JSONRPCRequest &request) -> UniValue {
2419  std::shared_ptr<CWallet> const rpc_wallet =
2420  GetWalletForJSONRPCRequest(request);
2421  if (!rpc_wallet) {
2422  return NullUniValue;
2423  }
2424  CWallet &wallet = *rpc_wallet;
2425 
2426  // Make sure the results are valid at least up to the most recent
2427  // block the user could have gotten from another RPC command prior
2428  // to now
2429  wallet.BlockUntilSyncedToCurrentChain();
2430 
2431  LOCK(wallet.cs_wallet);
2432 
2433  const auto bal = GetBalance(wallet);
2434  UniValue balances{UniValue::VOBJ};
2435  {
2436  UniValue balances_mine{UniValue::VOBJ};
2437  balances_mine.pushKV("trusted", bal.m_mine_trusted);
2438  balances_mine.pushKV("untrusted_pending",
2439  bal.m_mine_untrusted_pending);
2440  balances_mine.pushKV("immature", bal.m_mine_immature);
2441  if (wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE)) {
2442  // If the AVOID_REUSE flag is set, bal has been set to just
2443  // the un-reused address balance. Get the total balance, and
2444  // then subtract bal to get the reused address balance.
2445  const auto full_bal = GetBalance(wallet, 0, false);
2446  balances_mine.pushKV("used",
2447  full_bal.m_mine_trusted +
2448  full_bal.m_mine_untrusted_pending -
2449  bal.m_mine_trusted -
2450  bal.m_mine_untrusted_pending);
2451  }
2452  balances.pushKV("mine", balances_mine);
2453  }
2454  auto spk_man = wallet.GetLegacyScriptPubKeyMan();
2455  if (spk_man && spk_man->HaveWatchOnly()) {
2456  UniValue balances_watchonly{UniValue::VOBJ};
2457  balances_watchonly.pushKV("trusted", bal.m_watchonly_trusted);
2458  balances_watchonly.pushKV("untrusted_pending",
2459  bal.m_watchonly_untrusted_pending);
2460  balances_watchonly.pushKV("immature", bal.m_watchonly_immature);
2461  balances.pushKV("watchonly", balances_watchonly);
2462  }
2463  return balances;
2464  },
2465  };
2466 }
2467 
2469  return RPCHelpMan{
2470  "getwalletinfo",
2471  "Returns an object containing various wallet state info.\n",
2472  {},
2473  RPCResult{
2475  "",
2476  "",
2477  {{
2478  {RPCResult::Type::STR, "walletname", "the wallet name"},
2479  {RPCResult::Type::NUM, "walletversion", "the wallet version"},
2480  {RPCResult::Type::STR_AMOUNT, "balance",
2481  "DEPRECATED. Identical to getbalances().mine.trusted"},
2482  {RPCResult::Type::STR_AMOUNT, "unconfirmed_balance",
2483  "DEPRECATED. Identical to "
2484  "getbalances().mine.untrusted_pending"},
2485  {RPCResult::Type::STR_AMOUNT, "immature_balance",
2486  "DEPRECATED. Identical to getbalances().mine.immature"},
2487  {RPCResult::Type::NUM, "txcount",
2488  "the total number of transactions in the wallet"},
2489  {RPCResult::Type::NUM_TIME, "keypoololdest",
2490  "the " + UNIX_EPOCH_TIME +
2491  " of the oldest pre-generated key in the key pool. "
2492  "Legacy wallets only."},
2493  {RPCResult::Type::NUM, "keypoolsize",
2494  "how many new keys are pre-generated (only counts external "
2495  "keys)"},
2496  {RPCResult::Type::NUM, "keypoolsize_hd_internal",
2497  "how many new keys are pre-generated for internal use (used "
2498  "for change outputs, only appears if the wallet is using "
2499  "this feature, otherwise external keys are used)"},
2500  {RPCResult::Type::NUM_TIME, "unlocked_until",
2501  /* optional */ true,
2502  "the " + UNIX_EPOCH_TIME +
2503  " until which the wallet is unlocked for transfers, or 0 "
2504  "if the wallet is locked (only present for "
2505  "passphrase-encrypted wallets)"},
2506  {RPCResult::Type::STR_AMOUNT, "paytxfee",
2507  "the transaction fee configuration, set in " +
2508  Currency::get().ticker + "/kB"},
2509  {RPCResult::Type::STR_HEX, "hdseedid", /* optional */ true,
2510  "the Hash160 of the HD seed (only present when HD is "
2511  "enabled)"},
2512  {RPCResult::Type::BOOL, "private_keys_enabled",
2513  "false if privatekeys are disabled for this wallet (enforced "
2514  "watch-only wallet)"},
2516  "scanning",
2517  "current scanning details, or false if no scan is in "
2518  "progress",
2519  {
2520  {RPCResult::Type::NUM, "duration",
2521  "elapsed seconds since scan start"},
2522  {RPCResult::Type::NUM, "progress",
2523  "scanning progress percentage [0.0, 1.0]"},
2524  },
2525  /*skip_type_check=*/true},
2526  {RPCResult::Type::BOOL, "avoid_reuse",
2527  "whether this wallet tracks clean/dirty coins in terms of "
2528  "reuse"},
2529  {RPCResult::Type::BOOL, "descriptors",
2530  "whether this wallet uses descriptors for scriptPubKey "
2531  "management"},
2532  }},
2533  },
2534  RPCExamples{HelpExampleCli("getwalletinfo", "") +
2535  HelpExampleRpc("getwalletinfo", "")},
2536  [&](const RPCHelpMan &self, const Config &config,
2537  const JSONRPCRequest &request) -> UniValue {
2538  std::shared_ptr<CWallet> const wallet =
2539  GetWalletForJSONRPCRequest(request);
2540  if (!wallet) {
2541  return NullUniValue;
2542  }
2543  const CWallet *const pwallet = wallet.get();
2544 
2545  // Make sure the results are valid at least up to the most recent
2546  // block the user could have gotten from another RPC command prior
2547  // to now
2548  pwallet->BlockUntilSyncedToCurrentChain();
2549 
2550  LOCK(pwallet->cs_wallet);
2551 
2552  UniValue obj(UniValue::VOBJ);
2553 
2554  size_t kpExternalSize = pwallet->KeypoolCountExternalKeys();
2555  const auto bal = GetBalance(*pwallet);
2556  int64_t kp_oldest = pwallet->GetOldestKeyPoolTime();
2557  obj.pushKV("walletname", pwallet->GetName());
2558  obj.pushKV("walletversion", pwallet->GetVersion());
2559  obj.pushKV("balance", bal.m_mine_trusted);
2560  obj.pushKV("unconfirmed_balance", bal.m_mine_untrusted_pending);
2561  obj.pushKV("immature_balance", bal.m_mine_immature);
2562  obj.pushKV("txcount", (int)pwallet->mapWallet.size());
2563  if (kp_oldest > 0) {
2564  obj.pushKV("keypoololdest", kp_oldest);
2565  }
2566  obj.pushKV("keypoolsize", (int64_t)kpExternalSize);
2567 
2568  LegacyScriptPubKeyMan *spk_man =
2569  pwallet->GetLegacyScriptPubKeyMan();
2570  if (spk_man) {
2571  CKeyID seed_id = spk_man->GetHDChain().seed_id;
2572  if (!seed_id.IsNull()) {
2573  obj.pushKV("hdseedid", seed_id.GetHex());
2574  }
2575  }
2576 
2577  if (pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) {
2578  obj.pushKV("keypoolsize_hd_internal",
2579  int64_t(pwallet->GetKeyPoolSize() - kpExternalSize));
2580  }
2581  if (pwallet->IsCrypted()) {
2582  obj.pushKV("unlocked_until", pwallet->nRelockTime);
2583  }
2584  obj.pushKV("paytxfee", pwallet->m_pay_tx_fee.GetFeePerK());
2585  obj.pushKV(
2586  "private_keys_enabled",
2588  if (pwallet->IsScanning()) {
2589  UniValue scanning(UniValue::VOBJ);
2590  scanning.pushKV("duration", pwallet->ScanningDuration() / 1000);
2591  scanning.pushKV("progress", pwallet->ScanningProgress());
2592  obj.pushKV("scanning", scanning);
2593  } else {
2594  obj.pushKV("scanning", false);
2595  }
2596  obj.pushKV("avoid_reuse",
2598  obj.pushKV("descriptors",
2600  return obj;
2601  },
2602  };
2603 }
2604 
2606  return RPCHelpMan{
2607  "listwalletdir",
2608  "Returns a list of wallets in the wallet directory.\n",
2609  {},
2610  RPCResult{
2612  "",
2613  "",
2614  {
2616  "wallets",
2617  "",
2618  {
2620  "",
2621  "",
2622  {
2623  {RPCResult::Type::STR, "name", "The wallet name"},
2624  }},
2625  }},
2626  }},
2627  RPCExamples{HelpExampleCli("listwalletdir", "") +
2628  HelpExampleRpc("listwalletdir", "")},
2629  [&](const RPCHelpMan &self, const Config &config,
2630  const JSONRPCRequest &request) -> UniValue {
2631  UniValue wallets(UniValue::VARR);
2632  for (const auto &path : ListWalletDir()) {
2634  wallet.pushKV("name", path.u8string());
2635  wallets.push_back(wallet);
2636  }
2637 
2638  UniValue result(UniValue::VOBJ);
2639  result.pushKV("wallets", wallets);
2640  return result;
2641  },
2642  };
2643 }
2644 
2646  return RPCHelpMan{
2647  "listwallets",
2648  "Returns a list of currently loaded wallets.\n"
2649  "For full information on the wallet, use \"getwalletinfo\"\n",
2650  {},
2652  "",
2653  "",
2654  {
2655  {RPCResult::Type::STR, "walletname", "the wallet name"},
2656  }},
2657  RPCExamples{HelpExampleCli("listwallets", "") +
2658  HelpExampleRpc("listwallets", "")},
2659  [&](const RPCHelpMan &self, const Config &config,
2660  const JSONRPCRequest &request) -> UniValue {
2661  UniValue obj(UniValue::VARR);
2662 
2663  for (const std::shared_ptr<CWallet> &wallet : GetWallets()) {
2664  LOCK(wallet->cs_wallet);
2665  obj.push_back(wallet->GetName());
2666  }
2667 
2668  return obj;
2669  },
2670  };
2671 }
2672 
2674  return RPCHelpMan{
2675  "loadwallet",
2676  "Loads a wallet from a wallet file or directory."
2677  "\nNote that all wallet command-line options used when starting "
2678  "bitcoind will be"
2679  "\napplied to the new wallet (eg -rescan, etc).\n",
2680  {
2682  "The wallet directory or .dat file."},
2683  {"load_on_startup", RPCArg::Type::BOOL,
2685  "Save wallet name to persistent settings and load on startup. "
2686  "True to add wallet to startup list, false to remove, null to "
2687  "leave unchanged."},
2688  },
2690  "",
2691  "",
2692  {
2693  {RPCResult::Type::STR, "name",
2694  "The wallet name if loaded successfully."},
2695  {RPCResult::Type::STR, "warning",
2696  "Warning message if wallet was not loaded cleanly."},
2697  }},
2698  RPCExamples{HelpExampleCli("loadwallet", "\"test.dat\"") +
2699  HelpExampleRpc("loadwallet", "\"test.dat\"")},
2700  [&](const RPCHelpMan &self, const Config &config,
2701  const JSONRPCRequest &request) -> UniValue {
2702  WalletContext &context = EnsureWalletContext(request.context);
2703  const std::string name(request.params[0].get_str());
2704 
2705  auto [wallet, warnings] =
2706  LoadWalletHelper(context, request.params[1], name);
2707 
2708  UniValue obj(UniValue::VOBJ);
2709  obj.pushKV("name", wallet->GetName());
2710  obj.pushKV("warning", Join(warnings, Untranslated("\n")).original);
2711 
2712  return obj;
2713  },
2714  };
2715 }
2716 
2718  std::string flags = "";
2719  for (auto &it : WALLET_FLAG_MAP) {
2720  if (it.second & MUTABLE_WALLET_FLAGS) {
2721  flags += (flags == "" ? "" : ", ") + it.first;
2722  }
2723  }
2724  return RPCHelpMan{
2725  "setwalletflag",
2726  "Change the state of the given wallet flag for a wallet.\n",
2727  {
2729  "The name of the flag to change. Current available flags: " +
2730  flags},
2731  {"value", RPCArg::Type::BOOL, RPCArg::Default{true},
2732  "The new state."},
2733  },
2735  "",
2736  "",
2737  {
2738  {RPCResult::Type::STR, "flag_name",
2739  "The name of the flag that was modified"},
2740  {RPCResult::Type::BOOL, "flag_state",
2741  "The new state of the flag"},
2742  {RPCResult::Type::STR, "warnings",
2743  "Any warnings associated with the change"},
2744  }},
2745  RPCExamples{HelpExampleCli("setwalletflag", "avoid_reuse") +
2746  HelpExampleRpc("setwalletflag", "\"avoid_reuse\"")},
2747  [&](const RPCHelpMan &self, const Config &config,
2748  const JSONRPCRequest &request) -> UniValue {
2749  std::shared_ptr<CWallet> const wallet =
2750  GetWalletForJSONRPCRequest(request);
2751  if (!wallet) {
2752  return NullUniValue;
2753  }
2754  CWallet *const pwallet = wallet.get();
2755 
2756  std::string flag_str = request.params[0].get_str();
2757  bool value =
2758  request.params[1].isNull() || request.params[1].get_bool();
2759 
2760  if (!WALLET_FLAG_MAP.count(flag_str)) {
2761  throw JSONRPCError(
2763  strprintf("Unknown wallet flag: %s", flag_str));
2764  }
2765 
2766  auto flag = WALLET_FLAG_MAP.at(flag_str);
2767 
2768  if (!(flag & MUTABLE_WALLET_FLAGS)) {
2769  throw JSONRPCError(
2771  strprintf("Wallet flag is immutable: %s", flag_str));
2772  }
2773 
2774  UniValue res(UniValue::VOBJ);
2775 
2776  if (pwallet->IsWalletFlagSet(flag) == value) {
2777  throw JSONRPCError(
2779  strprintf("Wallet flag is already set to %s: %s",
2780  value ? "true" : "false", flag_str));
2781  }
2782 
2783  res.pushKV("flag_name", flag_str);
2784  res.pushKV("flag_state", value);
2785 
2786  if (value) {
2787  pwallet->SetWalletFlag(flag);
2788  } else {
2789  pwallet->UnsetWalletFlag(flag);
2790  }
2791 
2792  if (flag && value && WALLET_FLAG_CAVEATS.count(flag)) {
2793  res.pushKV("warnings", WALLET_FLAG_CAVEATS.at(flag));
2794  }
2795 
2796  return res;
2797  },
2798  };
2799 }
2800 
2802  return RPCHelpMan{
2803  "createwallet",
2804  "Creates and loads a new wallet.\n",
2805  {
2806  {"wallet_name", RPCArg::Type::STR, RPCArg::Optional::NO,
2807  "The name for the new wallet. If this is a path, the wallet will "
2808  "be created at the path location."},
2809  {"disable_private_keys", RPCArg::Type::BOOL, RPCArg::Default{false},
2810  "Disable the possibility of private keys (only watchonlys are "
2811  "possible in this mode)."},
2812  {"blank", RPCArg::Type::BOOL, RPCArg::Default{false},
2813  "Create a blank wallet. A blank wallet has no keys or HD seed. "
2814  "One can be set using sethdseed."},
2816  "Encrypt the wallet with this passphrase."},
2817  {"avoid_reuse", RPCArg::Type::BOOL, RPCArg::Default{false},
2818  "Keep track of coin reuse, and treat dirty and clean coins "
2819  "differently with privacy considerations in mind."},
2820  {"descriptors", RPCArg::Type::BOOL, RPCArg::Default{false},
2821  "Create a native descriptor wallet. The wallet will use "
2822  "descriptors internally to handle address creation"},
2823  {"load_on_startup", RPCArg::Type::BOOL,
2825  "Save wallet name to persistent settings and load on startup. "
2826  "True to add wallet to startup list, false to remove, null to "
2827  "leave unchanged."},
2828  },
2830  "",
2831  "",
2832  {
2833  {RPCResult::Type::STR, "name",
2834  "The wallet name if created successfully. If the wallet "
2835  "was created using a full path, the wallet_name will be "
2836  "the full path."},
2837  {RPCResult::Type::STR, "warning",
2838  "Warning message if wallet was not loaded cleanly."},
2839  }},
2840  RPCExamples{
2841  HelpExampleCli("createwallet", "\"testwallet\"") +
2842  HelpExampleRpc("createwallet", "\"testwallet\"") +
2843  HelpExampleCliNamed("createwallet", {{"wallet_name", "descriptors"},
2844  {"avoid_reuse", true},
2845  {"descriptors", true},
2846  {"load_on_startup", true}}) +
2847  HelpExampleRpcNamed("createwallet", {{"wallet_name", "descriptors"},
2848  {"avoid_reuse", true},
2849  {"descriptors", true},
2850  {"load_on_startup", true}})},
2851  [&](const RPCHelpMan &self, const Config &config,
2852  const JSONRPCRequest &request) -> UniValue {
2853  WalletContext &context = EnsureWalletContext(request.context);
2854  uint64_t flags = 0;
2855  if (!request.params[1].isNull() && request.params[1].get_bool()) {
2857  }
2858 
2859  if (!request.params[2].isNull() && request.params[2].get_bool()) {
2861  }
2862 
2863  SecureString passphrase;
2864  passphrase.reserve(100);
2865  std::vector<bilingual_str> warnings;
2866  if (!request.params[3].isNull()) {
2867  passphrase = request.params[3].get_str().c_str();
2868  if (passphrase.empty()) {
2869  // Empty string means unencrypted
2870  warnings.emplace_back(Untranslated(
2871  "Empty string given as passphrase, wallet will "
2872  "not be encrypted."));
2873  }
2874  }
2875 
2876  if (!request.params[4].isNull() && request.params[4].get_bool()) {
2878  }
2879  if (!request.params[5].isNull() && request.params[5].get_bool()) {
2881  warnings.emplace_back(Untranslated(
2882  "Wallet is an experimental descriptor wallet"));
2883  }
2884 
2885  DatabaseOptions options;
2886  DatabaseStatus status;
2887  options.require_create = true;
2888  options.create_flags = flags;
2889  options.create_passphrase = passphrase;
2891  std::optional<bool> load_on_start =
2892  request.params[6].isNull()
2893  ? std::nullopt
2894  : std::make_optional<bool>(request.params[6].get_bool());
2895  std::shared_ptr<CWallet> wallet =
2896  CreateWallet(*context.chain, request.params[0].get_str(),
2897  load_on_start, options, status, error, warnings);
2898  if (!wallet) {
2901  : RPC_WALLET_ERROR;
2902  throw JSONRPCError(code, error.original);
2903  }
2904 
2905  UniValue obj(UniValue::VOBJ);
2906  obj.pushKV("name", wallet->GetName());
2907  obj.pushKV("warning", Join(warnings, Untranslated("\n")).original);
2908 
2909  return obj;
2910  },
2911  };
2912 }
2913 
2915  return RPCHelpMan{
2916  "unloadwallet",
2917  "Unloads the wallet referenced by the request endpoint otherwise "
2918  "unloads the wallet specified in the argument.\n"
2919  "Specifying the wallet name on a wallet endpoint is invalid.",
2920  {
2921  {"wallet_name", RPCArg::Type::STR,
2922  RPCArg::DefaultHint{"the wallet name from the RPC request"},
2923  "The name of the wallet to unload."},
2924  {"load_on_startup", RPCArg::Type::BOOL,
2926  "Save wallet name to persistent settings and load on startup. "
2927  "True to add wallet to startup list, false to remove, null to "
2928  "leave unchanged."},
2929  },
2931  "",
2932  "",
2933  {
2934  {RPCResult::Type::STR, "warning",
2935  "Warning message if wallet was not unloaded cleanly."},
2936  }},
2937  RPCExamples{HelpExampleCli("unloadwallet", "wallet_name") +
2938  HelpExampleRpc("unloadwallet", "wallet_name")},
2939  [&](const RPCHelpMan &self, const Config &config,
2940  const JSONRPCRequest &request) -> UniValue {
2941  std::string wallet_name;
2942  if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
2943  if (!request.params[0].isNull()) {
2945  "Cannot unload the requested wallet");
2946  }
2947  } else {
2948  wallet_name = request.params[0].get_str();
2949  }
2950 
2951  std::shared_ptr<CWallet> wallet = GetWallet(wallet_name);
2952  if (!wallet) {
2953  throw JSONRPCError(
2955  "Requested wallet does not exist or is not loaded");
2956  }
2957 
2958  // Release the "main" shared pointer and prevent further
2959  // notifications. Note that any attempt to load the same wallet
2960  // would fail until the wallet is destroyed (see CheckUniqueFileid).
2961  std::vector<bilingual_str> warnings;
2962  std::optional<bool> load_on_start =
2963  request.params[1].isNull()
2964  ? std::nullopt
2965  : std::make_optional<bool>(request.params[1].get_bool());
2966  if (!RemoveWallet(wallet, load_on_start, warnings)) {
2968  "Requested wallet already unloaded");
2969  }
2970 
2971  UnloadWallet(std::move(wallet));
2972 
2973  UniValue result(UniValue::VOBJ);
2974  result.pushKV("warning",
2975  Join(warnings, Untranslated("\n")).original);
2976  return result;
2977  },
2978  };
2979 }
2980 
2982  const auto &ticker = Currency::get().ticker;
2983  return RPCHelpMan{
2984  "listunspent",
2985  "Returns array of unspent transaction outputs\n"
2986  "with between minconf and maxconf (inclusive) confirmations.\n"
2987  "Optionally filter to only include txouts paid to specified "
2988  "addresses.\n",
2989  {
2990  {"minconf", RPCArg::Type::NUM, RPCArg::Default{1},
2991  "The minimum confirmations to filter"},
2992  {"maxconf", RPCArg::Type::NUM, RPCArg::Default{9999999},
2993  "The maximum confirmations to filter"},
2994  {
2995  "addresses",
2998  "The bitcoin addresses to filter",
2999  {
3001  "bitcoin address"},
3002  },
3003  },
3004  {"include_unsafe", RPCArg::Type::BOOL, RPCArg::Default{true},
3005  "Include outputs that are not safe to spend\n"
3006  " See description of \"safe\" attribute below."},
3007  {"query_options",
3010  "JSON with query options",
3011  {
3012  {"minimumAmount", RPCArg::Type::AMOUNT,
3014  "Minimum value of each UTXO in " + ticker + ""},
3015  {"maximumAmount", RPCArg::Type::AMOUNT,
3016  RPCArg::DefaultHint{"unlimited"},
3017  "Maximum value of each UTXO in " + ticker + ""},
3018  {"maximumCount", RPCArg::Type::NUM,
3019  RPCArg::DefaultHint{"unlimited"}, "Maximum number of UTXOs"},
3020  {"minimumSumAmount", RPCArg::Type::AMOUNT,
3021  RPCArg::DefaultHint{"unlimited"},
3022  "Minimum sum value of all UTXOs in " + ticker + ""},
3023  },
3024  RPCArgOptions{.oneline_description = "query_options"}},
3025  },
3026  RPCResult{
3028  "",
3029  "",
3030  {
3032  "",
3033  "",
3034  {
3035  {RPCResult::Type::STR_HEX, "txid", "the transaction id"},
3036  {RPCResult::Type::NUM, "vout", "the vout value"},
3037  {RPCResult::Type::STR, "address", "the bitcoin address"},
3038  {RPCResult::Type::STR, "label",
3039  "The associated label, or \"\" for the default label"},
3040  {RPCResult::Type::STR, "scriptPubKey", "the script key"},
3041  {RPCResult::Type::STR_AMOUNT, "amount",
3042  "the transaction output amount in " + ticker},
3043  {RPCResult::Type::NUM, "confirmations",
3044  "The number of confirmations"},
3045  {RPCResult::Type::NUM, "ancestorcount",
3046  /* optional */ true,
3047  "DEPRECATED: The number of in-mempool ancestor "
3048  "transactions, including this one (if transaction is in "
3049  "the mempool). Only displayed if the "
3050  "-deprecatedrpc=mempool_ancestors_descendants option is "
3051  "set"},
3052  {RPCResult::Type::NUM, "ancestorsize", /* optional */ true,
3053  "DEPRECATED: The virtual transaction size of in-mempool "
3054  " ancestors, including this one (if transaction is in "
3055  "the mempool). Only displayed if the "
3056  "-deprecatedrpc=mempool_ancestors_descendants option is "
3057  "set"},
3058  {RPCResult::Type::STR_AMOUNT, "ancestorfees",
3059  /* optional */ true,
3060  "DEPRECATED: The total fees of in-mempool ancestors "
3061  "(including this one) with fee deltas used for mining "
3062  "priority in " +
3063  ticker +
3064  " (if transaction is in the mempool). Only "
3065  "displayed if the "
3066  "-deprecatedrpc=mempool_ancestors_descendants option "
3067  "is "
3068  "set"},
3069  {RPCResult::Type::STR_HEX, "redeemScript",
3070  "The redeemScript if scriptPubKey is P2SH"},
3071  {RPCResult::Type::BOOL, "spendable",
3072  "Whether we have the private keys to spend this output"},
3073  {RPCResult::Type::BOOL, "solvable",
3074  "Whether we know how to spend this output, ignoring the "
3075  "lack of keys"},
3076  {RPCResult::Type::BOOL, "reused",
3077  "(only present if avoid_reuse is set) Whether this "
3078  "output is reused/dirty (sent to an address that was "
3079  "previously spent from)"},
3080  {RPCResult::Type::STR, "desc",
3081  "(only when solvable) A descriptor for spending this "
3082  "output"},
3083  {RPCResult::Type::BOOL, "safe",
3084  "Whether this output is considered safe to spend. "
3085  "Unconfirmed transactions\n"
3086  "from outside keys are considered unsafe\n"
3087  "and are not eligible for spending by fundrawtransaction "
3088  "and sendtoaddress."},
3089  }},
3090  }},
3091  RPCExamples{
3092  HelpExampleCli("listunspent", "") +
3093  HelpExampleCli("listunspent",
3094  "6 9999999 "
3095  "\"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\","
3096  "\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"") +
3097  HelpExampleRpc("listunspent",
3098  "6, 9999999 "
3099  "\"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\","
3100  "\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"") +
3102  "listunspent",
3103  "6 9999999 '[]' true '{ \"minimumAmount\": 0.005 }'") +
3105  "listunspent",
3106  "6, 9999999, [] , true, { \"minimumAmount\": 0.005 } ")},
3107  [&](const RPCHelpMan &self, const Config &config,
3108  const JSONRPCRequest &request) -> UniValue {
3109  std::shared_ptr<CWallet> const wallet =
3110  GetWalletForJSONRPCRequest(request);
3111  if (!wallet) {
3112  return NullUniValue;
3113  }
3114  const CWallet *const pwallet = wallet.get();
3115 
3116  int nMinDepth = 1;
3117  if (!request.params[0].isNull()) {
3118  nMinDepth = request.params[0].getInt<int>();
3119  }
3120 
3121  int nMaxDepth = 9999999;
3122  if (!request.params[1].isNull()) {
3123  nMaxDepth = request.params[1].getInt<int>();
3124  }
3125 
3126  std::set<CTxDestination> destinations;
3127  if (!request.params[2].isNull()) {
3128  UniValue inputs = request.params[2].get_array();
3129  for (size_t idx = 0; idx < inputs.size(); idx++) {
3130  const UniValue &input = inputs[idx];
3132  input.get_str(), wallet->GetChainParams());
3133  if (!IsValidDestination(dest)) {
3134  throw JSONRPCError(
3136  std::string("Invalid Bitcoin address: ") +
3137  input.get_str());
3138  }
3139  if (!destinations.insert(dest).second) {
3140  throw JSONRPCError(
3142  std::string(
3143  "Invalid parameter, duplicated address: ") +
3144  input.get_str());
3145  }
3146  }
3147  }
3148 
3149  bool include_unsafe = true;
3150  if (!request.params[3].isNull()) {
3151  include_unsafe = request.params[3].get_bool();
3152  }
3153 
3154  Amount nMinimumAmount = Amount::zero();
3155  Amount nMaximumAmount = MAX_MONEY;
3156  Amount nMinimumSumAmount = MAX_MONEY;
3157  uint64_t nMaximumCount = 0;
3158 
3159  if (!request.params[4].isNull()) {
3160  const UniValue &options = request.params[4].get_obj();
3161 
3163  options,
3164  {
3165  {"minimumAmount", UniValueType()},
3166  {"maximumAmount", UniValueType()},
3167  {"minimumSumAmount", UniValueType()},
3168  {"maximumCount", UniValueType(UniValue::VNUM)},
3169  },
3170  true, true);
3171 
3172  if (options.exists("minimumAmount")) {
3173  nMinimumAmount = AmountFromValue(options["minimumAmount"]);
3174  }
3175 
3176  if (options.exists("maximumAmount")) {
3177  nMaximumAmount = AmountFromValue(options["maximumAmount"]);
3178  }
3179 
3180  if (options.exists("minimumSumAmount")) {
3181  nMinimumSumAmount =
3182  AmountFromValue(options["minimumSumAmount"]);
3183  }
3184 
3185  if (options.exists("maximumCount")) {
3186  nMaximumCount = options["maximumCount"].getInt<int64_t>();
3187  }
3188  }
3189 
3190  // Make sure the results are valid at least up to the most recent
3191  // block the user could have gotten from another RPC command prior
3192  // to now
3193  pwallet->BlockUntilSyncedToCurrentChain();
3194 
3195  UniValue results(UniValue::VARR);
3196  std::vector<COutput> vecOutputs;
3197  {
3198  CCoinControl cctl;
3199  cctl.m_avoid_address_reuse = false;
3200  cctl.m_min_depth = nMinDepth;
3201  cctl.m_max_depth = nMaxDepth;
3202  cctl.m_include_unsafe_inputs = include_unsafe;
3203  LOCK(pwallet->cs_wallet);
3204  AvailableCoins(*pwallet, vecOutputs, &cctl, nMinimumAmount,
3205  nMaximumAmount, nMinimumSumAmount,
3206  nMaximumCount);
3207  }
3208 
3209  LOCK(pwallet->cs_wallet);
3210 
3211  const bool avoid_reuse =
3213 
3214  for (const COutput &out : vecOutputs) {
3215  CTxDestination address;
3216  const CScript &scriptPubKey =
3217  out.tx->tx->vout[out.i].scriptPubKey;
3218  bool fValidAddress = ExtractDestination(scriptPubKey, address);
3219  bool reused =
3220  avoid_reuse && pwallet->IsSpentKey(out.tx->GetId(), out.i);
3221 
3222  if (destinations.size() &&
3223  (!fValidAddress || !destinations.count(address))) {
3224  continue;
3225  }
3226 
3227  UniValue entry(UniValue::VOBJ);
3228  entry.pushKV("txid", out.tx->GetId().GetHex());
3229  entry.pushKV("vout", out.i);
3230 
3231  if (fValidAddress) {
3232  entry.pushKV("address", EncodeDestination(address, config));
3233 
3234  const auto *address_book_entry =
3235  pwallet->FindAddressBookEntry(address);
3236  if (address_book_entry) {
3237  entry.pushKV("label", address_book_entry->GetLabel());
3238  }
3239 
3240  std::unique_ptr<SigningProvider> provider =
3241  pwallet->GetSolvingProvider(scriptPubKey);
3242  if (provider) {
3243  if (scriptPubKey.IsPayToScriptHash()) {
3244  const CScriptID &hash =
3245  CScriptID(std::get<ScriptHash>(address));
3246  CScript redeemScript;
3247  if (provider->GetCScript(hash, redeemScript)) {
3248  entry.pushKV("redeemScript",
3249  HexStr(redeemScript));
3250  }
3251  }
3252  }
3253  }
3254 
3255  entry.pushKV("scriptPubKey", HexStr(scriptPubKey));
3256  entry.pushKV("amount", out.tx->tx->vout[out.i].nValue);
3257  entry.pushKV("confirmations", out.nDepth);
3258  entry.pushKV("spendable", out.fSpendable);
3259  entry.pushKV("solvable", out.fSolvable);
3260  if (out.fSolvable) {
3261  std::unique_ptr<SigningProvider> provider =
3262  pwallet->GetSolvingProvider(scriptPubKey);
3263  if (provider) {
3264  auto descriptor =
3265  InferDescriptor(scriptPubKey, *provider);
3266  entry.pushKV("desc", descriptor->ToString());
3267  }
3268  }
3269  if (avoid_reuse) {
3270  entry.pushKV("reused", reused);
3271  }
3272  entry.pushKV("safe", out.fSafe);
3273  results.push_back(entry);
3274  }
3275 
3276  return results;
3277  },
3278  };
3279 }
3280 
3282  Amount &fee_out, int &change_position,
3283  const UniValue &options, CCoinControl &coinControl) {
3284  // Make sure the results are valid at least up to the most recent block
3285  // the user could have gotten from another RPC command prior to now
3286  pwallet->BlockUntilSyncedToCurrentChain();
3287 
3288  change_position = -1;
3289  bool lockUnspents = false;
3290  UniValue subtractFeeFromOutputs;
3291  std::set<int> setSubtractFeeFromOutputs;
3292 
3293  if (!options.isNull()) {
3294  if (options.type() == UniValue::VBOOL) {
3295  // backward compatibility bool only fallback
3296  coinControl.fAllowWatchOnly = options.get_bool();
3297  } else {
3299  options,
3300  {
3301  {"add_inputs", UniValueType(UniValue::VBOOL)},
3302  {"include_unsafe", UniValueType(UniValue::VBOOL)},
3303  {"add_to_wallet", UniValueType(UniValue::VBOOL)},
3304  {"changeAddress", UniValueType(UniValue::VSTR)},
3305  {"change_address", UniValueType(UniValue::VSTR)},
3306  {"changePosition", UniValueType(UniValue::VNUM)},
3307  {"change_position", UniValueType(UniValue::VNUM)},
3308  {"includeWatching", UniValueType(UniValue::VBOOL)},
3309  {"include_watching", UniValueType(UniValue::VBOOL)},
3310  {"inputs", UniValueType(UniValue::VARR)},
3311  {"lockUnspents", UniValueType(UniValue::VBOOL)},
3312  {"lock_unspents", UniValueType(UniValue::VBOOL)},
3313  {"locktime", UniValueType(UniValue::VNUM)},
3314  // will be checked below
3315  {"feeRate", UniValueType()},
3316  {"fee_rate", UniValueType()},
3317  {"psbt", UniValueType(UniValue::VBOOL)},
3318  {"subtractFeeFromOutputs", UniValueType(UniValue::VARR)},
3319  {"subtract_fee_from_outputs", UniValueType(UniValue::VARR)},
3320  },
3321  true, true);
3322 
3323  if (options.exists("add_inputs")) {
3324  coinControl.m_add_inputs = options["add_inputs"].get_bool();
3325  }
3326 
3327  if (options.exists("changeAddress") ||
3328  options.exists("change_address")) {
3329  const std::string change_address_str =
3330  (options.exists("change_address")
3331  ? options["change_address"]
3332  : options["changeAddress"])
3333  .get_str();
3335  change_address_str, pwallet->GetChainParams());
3336 
3337  if (!IsValidDestination(dest)) {
3338  throw JSONRPCError(
3340  "Change address must be a valid bitcoin address");
3341  }
3342 
3343  coinControl.destChange = dest;
3344  }
3345 
3346  if (options.exists("changePosition") ||
3347  options.exists("change_position")) {
3348  change_position = (options.exists("change_position")
3349  ? options["change_position"]
3350  : options["changePosition"])
3351  .getInt<int>();
3352  }
3353 
3354  const UniValue include_watching_option =
3355  options.exists("include_watching") ? options["include_watching"]
3356  : options["includeWatching"];
3357  coinControl.fAllowWatchOnly =
3358  ParseIncludeWatchonly(include_watching_option, *pwallet);
3359 
3360  if (options.exists("lockUnspents") ||
3361  options.exists("lock_unspents")) {
3362  lockUnspents =
3363  (options.exists("lock_unspents") ? options["lock_unspents"]
3364  : options["lockUnspents"])
3365  .get_bool();
3366  }
3367 
3368  if (options.exists("include_unsafe")) {
3369  coinControl.m_include_unsafe_inputs =
3370  options["include_unsafe"].get_bool();
3371  }
3372 
3373  if (options.exists("feeRate") || options.exists("fee_rate")) {
3374  coinControl.m_feerate = CFeeRate(AmountFromValue(
3375  options.exists("fee_rate") ? options["fee_rate"]
3376  : options["feeRate"]));
3377  coinControl.fOverrideFeeRate = true;
3378  }
3379 
3380  if (options.exists("subtractFeeFromOutputs") ||
3381  options.exists("subtract_fee_from_outputs")) {
3382  subtractFeeFromOutputs =
3383  (options.exists("subtract_fee_from_outputs")
3384  ? options["subtract_fee_from_outputs"]
3385  : options["subtractFeeFromOutputs"])
3386  .get_array();
3387  }
3388  }
3389  } else {
3390  // if options is null and not a bool
3391  coinControl.fAllowWatchOnly =
3393  }
3394 
3395  if (tx.vout.size() == 0) {
3397  "TX must have at least one output");
3398  }
3399 
3400  if (change_position != -1 &&
3401  (change_position < 0 ||
3402  (unsigned int)change_position > tx.vout.size())) {
3404  "changePosition out of bounds");
3405  }
3406 
3407  for (size_t idx = 0; idx < subtractFeeFromOutputs.size(); idx++) {
3408  int pos = subtractFeeFromOutputs[idx].getInt<int>();
3409  if (setSubtractFeeFromOutputs.count(pos)) {
3410  throw JSONRPCError(
3412  strprintf("Invalid parameter, duplicated position: %d", pos));
3413  }
3414  if (pos < 0) {
3415  throw JSONRPCError(
3417  strprintf("Invalid parameter, negative position: %d", pos));
3418  }
3419  if (pos >= int(tx.vout.size())) {
3420  throw JSONRPCError(
3422  strprintf("Invalid parameter, position too large: %d", pos));
3423  }
3424  setSubtractFeeFromOutputs.insert(pos);
3425  }
3426 
3428 
3429  if (!FundTransaction(*pwallet, tx, fee_out, change_position, error,
3430  lockUnspents, setSubtractFeeFromOutputs,
3431  coinControl)) {
3432  throw JSONRPCError(RPC_WALLET_ERROR, error.original);
3433  }
3434 }
3435 
3437  const auto &ticker = Currency::get().ticker;
3438  return RPCHelpMan{
3439  "fundrawtransaction",
3440  "If the transaction has no inputs, they will be automatically selected "
3441  "to meet its out value.\n"
3442  "It will add at most one change output to the outputs.\n"
3443  "No existing outputs will be modified unless "
3444  "\"subtractFeeFromOutputs\" is specified.\n"
3445  "Note that inputs which were signed may need to be resigned after "
3446  "completion since in/outputs have been added.\n"
3447  "The inputs added will not be signed, use signrawtransactionwithkey or "
3448  "signrawtransactionwithwallet for that.\n"
3449  "Note that all existing inputs must have their previous output "
3450  "transaction be in the wallet.\n"
3451  "Note that all inputs selected must be of standard form and P2SH "
3452  "scripts must be\n"
3453  "in the wallet using importaddress or addmultisigaddress (to calculate "
3454  "fees).\n"
3455  "You can see whether this is the case by checking the \"solvable\" "
3456  "field in the listunspent output.\n"
3457  "Only pay-to-pubkey, multisig, and P2SH versions thereof are currently "
3458  "supported for watch-only\n",
3459  {
3461  "The hex string of the raw transaction"},
3462  {"options",
3465  "For backward compatibility: passing in a true instead of an "
3466  "object will result in {\"includeWatching\":true}",
3467  {
3468  {"add_inputs", RPCArg::Type::BOOL, RPCArg::Default{true},
3469  "For a transaction with existing inputs, automatically "
3470  "include more if they are not enough."},
3471  {"include_unsafe", RPCArg::Type::BOOL, RPCArg::Default{false},
3472  "Include inputs that are not safe to spend (unconfirmed "
3473  "transactions from outside keys).\n"
3474  "Warning: the resulting transaction may become invalid if "
3475  "one of the unsafe inputs disappears.\n"
3476  "If that happens, you will need to fund the transaction with "
3477  "different inputs and republish it."},
3478  {"changeAddress", RPCArg::Type::STR,
3479  RPCArg::DefaultHint{"pool address"},
3480  "The bitcoin address to receive the change"},
3481  {"changePosition", RPCArg::Type::NUM,
3482  RPCArg::DefaultHint{"random"},
3483  "The index of the change output"},
3484  {"includeWatching", RPCArg::Type::BOOL,
3486  "true for watch-only wallets, otherwise false"},
3487  "Also select inputs which are watch only.\n"
3488  "Only solvable inputs can be used. Watch-only destinations "
3489  "are solvable if the public key and/or output script was "
3490  "imported,\n"
3491  "e.g. with 'importpubkey' or 'importmulti' with the "
3492  "'pubkeys' or 'desc' field."},
3493  {"lockUnspents", RPCArg::Type::BOOL, RPCArg::Default{false},
3494  "Lock selected unspent outputs"},
3495  {"feeRate", RPCArg::Type::AMOUNT,
3497  "not set: makes wallet determine the fee"},
3498  "Set a specific fee rate in " + ticker + "/kB",
3499  RPCArgOptions{.also_positional = true}},
3500  {
3501  "subtractFeeFromOutputs",
3504  "The integers.\n"
3505  " The fee will be equally "
3506  "deducted from the amount of each specified output.\n"
3507  " Those recipients will "
3508  "receive less bitcoins than you enter in their "
3509  "corresponding amount field.\n"
3510  " If no outputs are "
3511  "specified here, the sender pays the fee.",
3512  {
3513  {"vout_index", RPCArg::Type::NUM,
3515  "The zero-based output index, before a change output "
3516  "is added."},
3517  },
3518  },
3519  },
3521  .oneline_description = "options"}},
3522  },
3524  "",
3525  "",
3526  {
3527  {RPCResult::Type::STR_HEX, "hex",
3528  "The resulting raw transaction (hex-encoded string)"},
3530  "Fee in " + ticker + " the resulting transaction pays"},
3531  {RPCResult::Type::NUM, "changepos",
3532  "The position of the added change output, or -1"},
3533  }},
3534  RPCExamples{
3535  "\nCreate a transaction with no inputs\n" +
3536  HelpExampleCli("createrawtransaction",
3537  "\"[]\" \"{\\\"myaddress\\\":10000}\"") +
3538  "\nAdd sufficient unsigned inputs to meet the output value\n" +
3539  HelpExampleCli("fundrawtransaction", "\"rawtransactionhex\"") +
3540  "\nSign the transaction\n" +
3541  HelpExampleCli("signrawtransactionwithwallet",
3542  "\"fundedtransactionhex\"") +
3543  "\nSend the transaction\n" +
3544  HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")},
3545  [&](const RPCHelpMan &self, const Config &config,
3546  const JSONRPCRequest &request) -> UniValue {
3547  std::shared_ptr<CWallet> const wallet =
3548  GetWalletForJSONRPCRequest(request);
3549  if (!wallet) {
3550  return NullUniValue;
3551  }
3552  CWallet *const pwallet = wallet.get();
3553 
3554  // parse hex string from parameter
3556  if (!DecodeHexTx(tx, request.params[0].get_str())) {
3558  "TX decode failed");
3559  }
3560 
3561  Amount fee;
3562  int change_position;
3563  CCoinControl coin_control;
3564  // Automatically select (additional) coins. Can be overridden by
3565  // options.add_inputs.
3566  coin_control.m_add_inputs = true;
3567  FundTransaction(pwallet, tx, fee, change_position,
3568  request.params[1], coin_control);
3569 
3570  UniValue result(UniValue::VOBJ);
3571  result.pushKV("hex", EncodeHexTx(CTransaction(tx)));
3572  result.pushKV("fee", fee);
3573  result.pushKV("changepos", change_position);
3574 
3575  return result;
3576  },
3577  };
3578 }
3579 
3581  return RPCHelpMan{
3582  "signrawtransactionwithwallet",
3583  "Sign inputs for raw transaction (serialized, hex-encoded).\n"
3584  "The second optional argument (may be null) is an array of previous "
3585  "transaction outputs that\n"
3586  "this transaction depends on but may not yet be in the block chain.\n" +
3588  {
3589  {"hexstring", RPCArg::Type::STR, RPCArg::Optional::NO,
3590  "The transaction hex string"},
3591  {
3592  "prevtxs",
3595  "The previous dependent transaction outputs",
3596  {
3597  {
3598  "",
3601  "",
3602  {
3603  {"txid", RPCArg::Type::STR_HEX,
3604  RPCArg::Optional::NO, "The transaction id"},
3606  "The output number"},
3607  {"scriptPubKey", RPCArg::Type::STR_HEX,
3608  RPCArg::Optional::NO, "script key"},
3609  {"redeemScript", RPCArg::Type::STR_HEX,
3610  RPCArg::Optional::OMITTED, "(required for P2SH)"},
3611  {"amount", RPCArg::Type::AMOUNT,
3612  RPCArg::Optional::NO, "The amount spent"},
3613  },
3614  },
3615  },
3616  },
3617  {"sighashtype", RPCArg::Type::STR, RPCArg::Default{"ALL|FORKID"},
3618  "The signature hash type. Must be one of\n"
3619  " \"ALL|FORKID\"\n"
3620  " \"NONE|FORKID\"\n"
3621  " \"SINGLE|FORKID\"\n"
3622  " \"ALL|FORKID|ANYONECANPAY\"\n"
3623  " \"NONE|FORKID|ANYONECANPAY\"\n"
3624  " \"SINGLE|FORKID|ANYONECANPAY\""},
3625  },
3626  RPCResult{
3628  "",
3629  "",
3630  {
3631  {RPCResult::Type::STR_HEX, "hex",
3632  "The hex-encoded raw transaction with signature(s)"},
3633  {RPCResult::Type::BOOL, "complete",
3634  "If the transaction has a complete set of signatures"},
3636  "errors",
3637  /* optional */ true,
3638  "Script verification errors (if there are any)",
3639  {
3641  "",
3642  "",
3643  {
3644  {RPCResult::Type::STR_HEX, "txid",
3645  "The hash of the referenced, previous transaction"},
3646  {RPCResult::Type::NUM, "vout",
3647  "The index of the output to spent and used as "
3648  "input"},
3649  {RPCResult::Type::STR_HEX, "scriptSig",
3650  "The hex-encoded signature script"},
3651  {RPCResult::Type::NUM, "sequence",
3652  "Script sequence number"},
3653  {RPCResult::Type::STR, "error",
3654  "Verification or signing error related to the "
3655  "input"},
3656  }},
3657  }},
3658  }},
3659  RPCExamples{
3660  HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") +
3661  HelpExampleRpc("signrawtransactionwithwallet", "\"myhex\"")},
3662  [&](const RPCHelpMan &self, const Config &config,
3663  const JSONRPCRequest &request) -> UniValue {
3664  std::shared_ptr<CWallet> const wallet =
3665  GetWalletForJSONRPCRequest(request);
3666  if (!wallet) {
3667  return NullUniValue;
3668  }
3669  const CWallet *const pwallet = wallet.get();
3670 
3671  CMutableTransaction mtx;
3672  if (!DecodeHexTx(mtx, request.params[0].get_str())) {
3674  "TX decode failed");
3675  }
3676 
3677  // Sign the transaction
3678  LOCK(pwallet->cs_wallet);
3679  EnsureWalletIsUnlocked(pwallet);
3680 
3681  // Fetch previous transactions (inputs):
3682  std::map<COutPoint, Coin> coins;
3683  for (const CTxIn &txin : mtx.vin) {
3684  // Create empty map entry keyed by prevout.
3685  coins[txin.prevout];
3686  }
3687  pwallet->chain().findCoins(coins);
3688 
3689  // Parse the prevtxs array
3690  ParsePrevouts(request.params[1], nullptr, coins);
3691 
3692  SigHashType nHashType = ParseSighashString(request.params[2]);
3693  if (!nHashType.hasForkId()) {
3695  "Signature must use SIGHASH_FORKID");
3696  }
3697 
3698  // Script verification errors
3699  std::map<int, std::string> input_errors;
3700 
3701  bool complete =
3702  pwallet->SignTransaction(mtx, coins, nHashType, input_errors);
3703  UniValue result(UniValue::VOBJ);
3704  SignTransactionResultToJSON(mtx, complete, coins, input_errors,
3705  result);
3706  return result;
3707  },
3708  };
3709 }
3710 
3712  return RPCHelpMan{
3713  "rescanblockchain",
3714  "Rescan the local blockchain for wallet related transactions.\n"
3715  "Note: Use \"getwalletinfo\" to query the scanning progress.\n",
3716  {
3717  {"start_height", RPCArg::Type::NUM, RPCArg::Default{0},
3718  "block height where the rescan should start"},
3719  {"stop_height", RPCArg::Type::NUM,
3721  "the last block height that should be scanned"},
3722  },
3723  RPCResult{
3725  "",
3726  "",
3727  {
3728  {RPCResult::Type::NUM, "start_height",
3729  "The block height where the rescan started (the requested "
3730  "height or 0)"},
3731  {RPCResult::Type::NUM, "stop_height",
3732  "The height of the last rescanned block. May be null in rare "
3733  "cases if there was a reorg and the call didn't scan any "
3734  "blocks because they were already scanned in the background."},
3735  }},
3736  RPCExamples{HelpExampleCli("rescanblockchain", "100000 120000") +
3737  HelpExampleRpc("rescanblockchain", "100000, 120000")},
3738  [&](const RPCHelpMan &self, const Config &config,
3739  const JSONRPCRequest &request) -> UniValue {
3740  std::shared_ptr<CWallet> const wallet =
3741  GetWalletForJSONRPCRequest(request);
3742  if (!wallet) {
3743  return NullUniValue;
3744  }
3745  CWallet *const pwallet = wallet.get();
3746 
3747  WalletRescanReserver reserver(*pwallet);
3748  if (!reserver.reserve()) {
3750  "Wallet is currently rescanning. Abort "
3751  "existing rescan or wait.");
3752  }
3753 
3754  int start_height = 0;
3755  std::optional<int> stop_height;
3756  BlockHash start_block;
3757  {
3758  LOCK(pwallet->cs_wallet);
3759  int tip_height = pwallet->GetLastBlockHeight();
3760 
3761  if (!request.params[0].isNull()) {
3762  start_height = request.params[0].getInt<int>();
3763  if (start_height < 0 || start_height > tip_height) {
3765  "Invalid start_height");
3766  }
3767  }
3768 
3769  if (!request.params[1].isNull()) {
3770  stop_height = request.params[1].getInt<int>();
3771  if (*stop_height < 0 || *stop_height > tip_height) {
3773  "Invalid stop_height");
3774  } else if (*stop_height < start_height) {
3775  throw JSONRPCError(
3777  "stop_height must be greater than start_height");
3778  }
3779  }
3780 
3781  // We can't rescan beyond non-pruned blocks, stop and throw an
3782  // error
3783  if (!pwallet->chain().hasBlocks(pwallet->GetLastBlockHash(),
3784  start_height, stop_height)) {
3785  throw JSONRPCError(
3787  "Can't rescan beyond pruned data. Use RPC call "
3788  "getblockchaininfo to determine your pruned height.");
3789  }
3790 
3792  pwallet->GetLastBlockHash(), start_height,
3793  FoundBlock().hash(start_block)));
3794  }
3795 
3797  start_block, start_height, stop_height, reserver,
3798  true /* fUpdate */);
3799  switch (result.status) {
3801  break;
3803  throw JSONRPCError(
3805  "Rescan failed. Potentially corrupted data files.");
3807  throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted.");
3808  // no default case, so the compiler can warn about missing
3809  // cases
3810  }
3812  response.pushKV("start_height", start_height);
3813  response.pushKV("stop_height", result.last_scanned_height
3814  ? *result.last_scanned_height
3815  : UniValue());
3816  return response;
3817  },
3818  };
3819 }
3820 
3822 public:
3824 
3825  void ProcessSubScript(const CScript &subscript, UniValue &obj) const {
3826  // Always present: script type and redeemscript
3827  std::vector<std::vector<uint8_t>> solutions_data;
3828  TxoutType which_type = Solver(subscript, solutions_data);
3829  obj.pushKV("script", GetTxnOutputType(which_type));
3830  obj.pushKV("hex", HexStr(subscript));
3831 
3832  CTxDestination embedded;
3833  if (ExtractDestination(subscript, embedded)) {
3834  // Only when the script corresponds to an address.
3835  UniValue subobj(UniValue::VOBJ);
3836  UniValue detail = DescribeAddress(embedded);
3837  subobj.pushKVs(detail);
3838  UniValue wallet_detail = std::visit(*this, embedded);
3839  subobj.pushKVs(wallet_detail);
3840  subobj.pushKV("address", EncodeDestination(embedded, GetConfig()));
3841  subobj.pushKV("scriptPubKey", HexStr(subscript));
3842  // Always report the pubkey at the top level, so that
3843  // `getnewaddress()['pubkey']` always works.
3844  if (subobj.exists("pubkey")) {
3845  obj.pushKV("pubkey", subobj["pubkey"]);
3846  }
3847  obj.pushKV("embedded", std::move(subobj));
3848  } else if (which_type == TxoutType::MULTISIG) {
3849  // Also report some information on multisig scripts (which do not
3850  // have a corresponding address).
3851  // TODO: abstract out the common functionality between this logic
3852  // and ExtractDestinations.
3853  obj.pushKV("sigsrequired", solutions_data[0][0]);
3854  UniValue pubkeys(UniValue::VARR);
3855  for (size_t i = 1; i < solutions_data.size() - 1; ++i) {
3856  CPubKey key(solutions_data[i].begin(), solutions_data[i].end());
3857  pubkeys.push_back(HexStr(key));
3858  }
3859  obj.pushKV("pubkeys", std::move(pubkeys));
3860  }
3861  }
3862 
3864  : provider(_provider) {}
3865 
3866  UniValue operator()(const CNoDestination &dest) const {
3867  return UniValue(UniValue::VOBJ);
3868  }
3869 
3870  UniValue operator()(const PKHash &pkhash) const {
3871  CKeyID keyID(ToKeyID(pkhash));
3872  UniValue obj(UniValue::VOBJ);
3873  CPubKey vchPubKey;
3874  if (provider && provider->GetPubKey(keyID, vchPubKey)) {
3875  obj.pushKV("pubkey", HexStr(vchPubKey));
3876  obj.pushKV("iscompressed", vchPubKey.IsCompressed());
3877  }
3878  return obj;
3879  }
3880 
3881  UniValue operator()(const ScriptHash &scripthash) const {
3882  CScriptID scriptID(scripthash);
3883  UniValue obj(UniValue::VOBJ);
3884  CScript subscript;
3885  if (provider && provider->GetCScript(scriptID, subscript)) {
3886  ProcessSubScript(subscript, obj);
3887  }
3888  return obj;
3889  }
3890 };
3891 
3892 static UniValue DescribeWalletAddress(const CWallet *const pwallet,
3893  const CTxDestination &dest) {
3894  UniValue ret(UniValue::VOBJ);
3895  UniValue detail = DescribeAddress(dest);
3896  CScript script = GetScriptForDestination(dest);
3897  std::unique_ptr<SigningProvider> provider = nullptr;
3898  if (pwallet) {
3899  provider = pwallet->GetSolvingProvider(script);
3900  }
3901  ret.pushKVs(detail);
3902  ret.pushKVs(std::visit(DescribeWalletAddressVisitor(provider.get()), dest));
3903  return ret;
3904 }
3905 
3908  const bool verbose) {
3909  UniValue ret(UniValue::VOBJ);
3910  if (verbose) {
3911  ret.pushKV("name", data.GetLabel());
3912  }
3913  ret.pushKV("purpose", data.purpose);
3914  return ret;
3915 }
3916 
3918  return RPCHelpMan{
3919  "getaddressinfo",
3920  "Return information about the given bitcoin address.\n"
3921  "Some of the information will only be present if the address is in the "
3922  "active wallet.\n",
3923  {
3925  "The bitcoin address for which to get information."},
3926  },
3927  RPCResult{
3929  "",
3930  "",
3931  {
3932  {RPCResult::Type::STR, "address",
3933  "The bitcoin address validated."},
3934  {RPCResult::Type::STR_HEX, "scriptPubKey",
3935  "The hex-encoded scriptPubKey generated by the address."},
3936  {RPCResult::Type::BOOL, "ismine", "If the address is yours."},
3937  {RPCResult::Type::BOOL, "iswatchonly",
3938  "If the address is watchonly."},
3939  {RPCResult::Type::BOOL, "solvable",
3940  "If we know how to spend coins sent to this address, ignoring "
3941  "the possible lack of private keys."},
3942  {RPCResult::Type::STR, "desc", /* optional */ true,
3943  "A descriptor for spending coins sent to this address (only "
3944  "when solvable)."},
3945  {RPCResult::Type::BOOL, "isscript", "If the key is a script."},
3946  {RPCResult::Type::BOOL, "ischange",
3947  "If the address was used for change output."},
3948  {RPCResult::Type::STR, "script", /* optional */ true,
3949  "The output script type. Only if isscript is true and the "
3950  "redeemscript is known. Possible\n"
3951  " "
3952  "types: nonstandard, pubkey, pubkeyhash, scripthash, "
3953  "multisig, nulldata."},
3954  {RPCResult::Type::STR_HEX, "hex", /* optional */ true,
3955  "The redeemscript for the p2sh address."},
3957  "pubkeys",
3958  /* optional */ true,
3959  "Array of pubkeys associated with the known redeemscript "
3960  "(only if script is multisig).",
3961  {
3962  {RPCResult::Type::STR, "pubkey", ""},
3963  }},
3964  {RPCResult::Type::NUM, "sigsrequired", /* optional */ true,
3965  "The number of signatures required to spend multisig output "
3966  "(only if script is multisig)."},
3967  {RPCResult::Type::STR_HEX, "pubkey", /* optional */ true,
3968  "The hex value of the raw public key for single-key addresses "
3969  "(possibly embedded in P2SH)."},
3971  "embedded",
3972  /* optional */ true,
3973  "Information about the address embedded in P2SH, if "
3974  "relevant and known.",
3975  {
3977  "Includes all getaddressinfo output fields for the "
3978  "embedded address excluding metadata (timestamp, "
3979  "hdkeypath, hdseedid)\n"
3980  "and relation to the wallet (ismine, iswatchonly)."},
3981  }},
3982  {RPCResult::Type::BOOL, "iscompressed", /* optional */ true,
3983  "If the pubkey is compressed."},
3984  {RPCResult::Type::NUM_TIME, "timestamp", /* optional */ true,
3985  "The creation time of the key, if available, expressed in " +
3986  UNIX_EPOCH_TIME + "."},
3987  {RPCResult::Type::STR, "hdkeypath", /* optional */ true,
3988  "The HD keypath, if the key is HD and available."},
3989  {RPCResult::Type::STR_HEX, "hdseedid", /* optional */ true,
3990  "The Hash160 of the HD seed."},
3991  {RPCResult::Type::STR_HEX, "hdmasterfingerprint",
3992  /* optional */ true, "The fingerprint of the master key."},
3994  "labels",
3995  "Array of labels associated with the address. Currently "
3996  "limited to one label but returned\n"
3997  "as an array to keep the API stable if multiple labels are "
3998  "enabled in the future.",
3999  {
4000  {RPCResult::Type::STR, "label name",
4001  "Label name (defaults to \"\")."},
4002  }},
4003  }},
4004  RPCExamples{HelpExampleCli("getaddressinfo", EXAMPLE_ADDRESS) +
4005  HelpExampleRpc("getaddressinfo", EXAMPLE_ADDRESS)},
4006  [&](const RPCHelpMan &self, const Config &config,
4007  const JSONRPCRequest &request) -> UniValue {
4008  std::shared_ptr<CWallet> const wallet =
4009  GetWalletForJSONRPCRequest(request);
4010  if (!wallet) {
4011  return NullUniValue;
4012  }
4013  const CWallet *const pwallet = wallet.get();
4014 
4015  LOCK(pwallet->cs_wallet);
4016 
4017  UniValue ret(UniValue::VOBJ);
4018  CTxDestination dest = DecodeDestination(request.params[0].get_str(),
4019  wallet->GetChainParams());
4020  // Make sure the destination is valid
4021  if (!IsValidDestination(dest)) {
4023  "Invalid address");
4024  }
4025 
4026  std::string currentAddress = EncodeDestination(dest, config);
4027  ret.pushKV("address", currentAddress);
4028 
4029  CScript scriptPubKey = GetScriptForDestination(dest);
4030  ret.pushKV("scriptPubKey", HexStr(scriptPubKey));
4031 
4032  std::unique_ptr<SigningProvider> provider =
4033  pwallet->GetSolvingProvider(scriptPubKey);
4034 
4035  isminetype mine = pwallet->IsMine(dest);
4036  ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE));
4037 
4038  bool solvable = provider && IsSolvable(*provider, scriptPubKey);
4039  ret.pushKV("solvable", solvable);
4040 
4041  if (solvable) {
4042  ret.pushKV(
4043  "desc",
4044  InferDescriptor(scriptPubKey, *provider)->ToString());
4045  }
4046 
4047  ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY));
4048 
4049  UniValue detail = DescribeWalletAddress(pwallet, dest);
4050  ret.pushKVs(detail);
4051 
4052  ret.pushKV("ischange", ScriptIsChange(*pwallet, scriptPubKey));
4053 
4054  ScriptPubKeyMan *spk_man =
4055  pwallet->GetScriptPubKeyMan(scriptPubKey);
4056  if (spk_man) {
4057  if (const std::unique_ptr<CKeyMetadata> meta =
4058  spk_man->GetMetadata(dest)) {
4059  ret.pushKV("timestamp", meta->nCreateTime);
4060  if (meta->has_key_origin) {
4061  ret.pushKV("hdkeypath",
4062  WriteHDKeypath(meta->key_origin.path));
4063  ret.pushKV("hdseedid", meta->hd_seed_id.GetHex());
4064  ret.pushKV("hdmasterfingerprint",
4065  HexStr(meta->key_origin.fingerprint));
4066  }
4067  }
4068  }
4069 
4070  // Return a `labels` array containing the label associated with the
4071  // address, equivalent to the `label` field above. Currently only
4072  // one label can be associated with an address, but we return an
4073  // array so the API remains stable if we allow multiple labels to be
4074  // associated with an address in the future.
4075  UniValue labels(UniValue::VARR);
4076  const auto *address_book_entry =
4077  pwallet->FindAddressBookEntry(dest);
4078  if (address_book_entry) {
4079  labels.push_back(address_book_entry->GetLabel());
4080  }
4081  ret.pushKV("labels", std::move(labels));
4082 
4083  return ret;
4084  },
4085  };
4086 }
4087 
4089  return RPCHelpMan{
4090  "getaddressesbylabel",
4091  "Returns the list of addresses assigned the specified label.\n",
4092  {
4093  {"label", RPCArg::Type::STR, RPCArg::Optional::NO, "The label."},
4094  },
4096  "",
4097  "json object with addresses as keys",
4098  {
4100  "address",
4101  "Information about address",
4102  {
4103  {RPCResult::Type::STR, "purpose",
4104  "Purpose of address (\"send\" for sending address, "
4105  "\"receive\" for receiving address)"},
4106  }},
4107  }},
4108  RPCExamples{HelpExampleCli("getaddressesbylabel", "\"tabby\"") +
4109  HelpExampleRpc("getaddressesbylabel", "\"tabby\"")},
4110  [&](const RPCHelpMan &self, const Config &config,
4111  const JSONRPCRequest &request) -> UniValue {
4112  std::shared_ptr<CWallet> const wallet =
4113  GetWalletForJSONRPCRequest(request);
4114  if (!wallet) {
4115  return NullUniValue;
4116  }
4117  const CWallet *const pwallet = wallet.get();
4118 
4119  LOCK(pwallet->cs_wallet);
4120 
4121  std::string label = LabelFromValue(request.params[0]);
4122 
4123  // Find all addresses that have the given label
4124  UniValue ret(UniValue::VOBJ);
4125  std::set<std::string> addresses;
4126  for (const std::pair<const CTxDestination, CAddressBookData> &item :
4127  pwallet->m_address_book) {
4128  if (item.second.IsChange()) {
4129  continue;
4130  }
4131  if (item.second.GetLabel() == label) {
4132  std::string address = EncodeDestination(item.first, config);
4133  // CWallet::m_address_book is not expected to contain
4134  // duplicate address strings, but build a separate set as a
4135  // precaution just in case it does.
4136  CHECK_NONFATAL(addresses.emplace(address).second);
4137  // UniValue::pushKV checks if the key exists in O(N)
4138  // and since duplicate addresses are unexpected (checked
4139  // with std::set in O(log(N))), UniValue::pushKVEnd is used
4140  // instead, which currently is O(1).
4141  ret.pushKVEnd(address,
4142  AddressBookDataToJSON(item.second, false));
4143  }
4144  }
4145 
4146  if (ret.empty()) {
4147  throw JSONRPCError(
4149  std::string("No addresses with label " + label));
4150  }
4151 
4152  return ret;
4153  },
4154  };
4155 }
4156 
4158  return RPCHelpMan{
4159  "listlabels",
4160  "Returns the list of all labels, or labels that are assigned to "
4161  "addresses with a specific purpose.\n",
4162  {
4164  "Address purpose to list labels for ('send','receive'). An empty "
4165  "string is the same as not providing this argument."},
4166  },
4168  "",
4169  "",
4170  {
4171  {RPCResult::Type::STR, "label", "Label name"},
4172  }},
4173  RPCExamples{"\nList all labels\n" + HelpExampleCli("listlabels", "") +
4174  "\nList labels that have receiving addresses\n" +
4175  HelpExampleCli("listlabels", "receive") +
4176  "\nList labels that have sending addresses\n" +
4177  HelpExampleCli("listlabels", "send") +
4178  "\nAs a JSON-RPC call\n" +
4179  HelpExampleRpc("listlabels", "receive")},
4180  [&](const RPCHelpMan &self, const Config &config,
4181  const JSONRPCRequest &request) -> UniValue {
4182  std::shared_ptr<CWallet> const wallet =
4183  GetWalletForJSONRPCRequest(request);
4184  if (!wallet) {
4185  return NullUniValue;
4186  }
4187  const CWallet *const pwallet = wallet.get();
4188 
4189  LOCK(pwallet->cs_wallet);
4190 
4191  std::string purpose;
4192  if (!request.params[0].isNull()) {
4193  purpose = request.params[0].get_str();
4194  }
4195 
4196  // Add to a set to sort by label name, then insert into Univalue
4197  // array
4198  std::set<std::string> label_set;
4199  for (const std::pair<const CTxDestination, CAddressBookData>
4200  &entry : pwallet->m_address_book) {
4201  if (entry.second.IsChange()) {
4202  continue;
4203  }
4204  if (purpose.empty() || entry.second.purpose == purpose) {
4205  label_set.insert(entry.second.GetLabel());
4206  }
4207  }
4208 
4209  UniValue ret(UniValue::VARR);
4210  for (const std::string &name : label_set) {
4211  ret.push_back(name);
4212  }
4213 
4214  return ret;
4215  },
4216  };
4217 }
4218 
4219 static RPCHelpMan send() {
4220  return RPCHelpMan{
4221  "send",
4222  "EXPERIMENTAL warning: this call may be changed in future releases.\n"
4223  "\nSend a transaction.\n",
4224  {
4225  {"outputs",
4228  "A JSON array with outputs (key-value pairs), where none of "
4229  "the keys are duplicated.\n"
4230  "That is, each address can only appear once and there can only "
4231  "be one 'data' object.\n"
4232  "For convenience, a dictionary, which holds the key-value "
4233  "pairs directly, is also accepted.",
4234  {
4235  {
4236  "",
4239  "",
4240  {
4242  "A key-value pair. The key (string) is the "
4243  "bitcoin address, the value (float or string) is "
4244  "the amount in " +
4245  Currency::get().ticker + ""},
4246  },
4247  },
4248  {
4249  "",
4252  "",
4253  {
4255  "A key-value pair. The key must be \"data\", the "
4256  "value is hex-encoded data"},
4257  },
4258  },
4259  },
4260  RPCArgOptions{.skip_type_check = true}},
4261  {"options",
4264  "",
4265  {
4266  {"add_inputs", RPCArg::Type::BOOL, RPCArg::Default{false},
4267  "If inputs are specified, automatically include more if they "
4268  "are not enough."},
4269  {"include_unsafe", RPCArg::Type::BOOL, RPCArg::Default{false},
4270  "Include inputs that are not safe to spend (unconfirmed "
4271  "transactions from outside keys).\n"
4272  "Warning: the resulting transaction may become invalid if "
4273  "one of the unsafe inputs disappears.\n"
4274  "If that happens, you will need to fund the transaction with "
4275  "different inputs and republish it."},
4276  {"add_to_wallet", RPCArg::Type::BOOL, RPCArg::Default{true},
4277  "When false, returns a serialized transaction which will not "
4278  "be added to the wallet or broadcast"},
4279  {"change_address", RPCArg::Type::STR,
4280  RPCArg::DefaultHint{"pool address"},
4281  "The bitcoin address to receive the change"},
4282  {"change_position", RPCArg::Type::NUM,
4283  RPCArg::DefaultHint{"random"},
4284  "The index of the change output"},
4285  {"fee_rate", RPCArg::Type::AMOUNT,
4287  "not set: makes wallet determine the fee"},
4288  "Set a specific fee rate in " + Currency::get().ticker +
4289  "/kB",
4290  RPCArgOptions{.also_positional = true}},
4291  {"include_watching", RPCArg::Type::BOOL,
4293  "true for watch-only wallets, otherwise false"},
4294  "Also select inputs which are watch only.\n"
4295  "Only solvable inputs can be used. Watch-only destinations "
4296  "are solvable if the public key and/or output script was "
4297  "imported,\n"
4298  "e.g. with 'importpubkey' or 'importmulti' with the "
4299  "'pubkeys' or 'desc' field."},
4300  {
4301  "inputs",
4304  "Specify inputs instead of adding them automatically. A "
4305  "JSON array of JSON objects",
4306  {
4308  "The transaction id"},
4310  "The output number"},
4312  "The sequence number"},
4313  },
4314  },
4315  {"locktime", RPCArg::Type::NUM, RPCArg::Default{0},
4316  "Raw locktime. Non-0 value also locktime-activates inputs"},
4317  {"lock_unspents", RPCArg::Type::BOOL, RPCArg::Default{false},
4318  "Lock selected unspent outputs"},
4319  {"psbt", RPCArg::Type::BOOL, RPCArg::DefaultHint{"automatic"},
4320  "Always return a PSBT, implies add_to_wallet=false."},
4321  {
4322  "subtract_fee_from_outputs",
4325  "Outputs to subtract the fee from, specified as integer "
4326  "indices.\n"
4327  "The fee will be equally deducted from the amount of each "
4328  "specified output.\n"
4329  "Those recipients will receive less bitcoins than you "
4330  "enter in their corresponding amount field.\n"
4331  "If no outputs are specified here, the sender pays the "
4332  "fee.",
4333  {
4334  {"vout_index", RPCArg::Type::NUM,
4336  "The zero-based output index, before a change output "
4337  "is added."},
4338  },
4339  },
4340  },
4341  RPCArgOptions{.oneline_description = "options"}},
4342  },
4343  RPCResult{
4345  "",
4346  "",
4347  {{RPCResult::Type::BOOL, "complete",
4348  "If the transaction has a complete set of signatures"},
4349  {RPCResult::Type::STR_HEX, "txid",
4350  "The transaction id for the send. Only 1 transaction is created "
4351  "regardless of the number of addresses."},
4352  {RPCResult::Type::STR_HEX, "hex",
4353  "If add_to_wallet is false, the hex-encoded raw transaction with "
4354  "signature(s)"},
4355  {RPCResult::Type::STR, "psbt",
4356  "If more signatures are needed, or if add_to_wallet is false, "
4357  "the base64-encoded (partially) signed transaction"}}},
4358  RPCExamples{
4359  ""
4360  "\nSend with a fee rate of 10 XEC/kB\n" +
4361  HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS +
4362  "\": 100000}' '{\"fee_rate\": 10}'\n") +
4363  "\nCreate a transaction with a specific input, and return "
4364  "result without adding to wallet or broadcasting to the "
4365  "network\n" +
4366  HelpExampleCli("send",
4367  "'{\"" + EXAMPLE_ADDRESS +
4368  "\": 100000}' '{\"add_to_wallet\": "
4369  "false, \"inputs\": "
4370  "[{\"txid\":"
4371  "\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b565"
4372  "5e72f463568df1aadf0\", \"vout\":1}]}'")},
4373  [&](const RPCHelpMan &self, const Config &config,
4374  const JSONRPCRequest &request) -> UniValue {
4375  std::shared_ptr<CWallet> const wallet =
4376  GetWalletForJSONRPCRequest(request);
4377  if (!wallet) {
4378  return NullUniValue;
4379  }
4380  CWallet *const pwallet = wallet.get();
4381 
4382  UniValue options = request.params[1];
4383  if (options.exists("changeAddress")) {
4384  throw JSONRPCError(RPC_INVALID_PARAMETER, "Use change_address");
4385  }
4386  if (options.exists("changePosition")) {
4388  "Use change_position");
4389  }
4390  if (options.exists("includeWatching")) {
4392  "Use include_watching");
4393  }
4394  if (options.exists("lockUnspents")) {
4395  throw JSONRPCError(RPC_INVALID_PARAMETER, "Use lock_unspents");
4396  }
4397  if (options.exists("subtractFeeFromOutputs")) {
4399  "Use subtract_fee_from_outputs");
4400  }
4401  if (options.exists("feeRate")) {
4402  throw JSONRPCError(RPC_INVALID_PARAMETER, "Use fee_rate");
4403  }
4404 
4405  const bool psbt_opt_in =
4406  options.exists("psbt") && options["psbt"].get_bool();
4407 
4408  Amount fee;
4409  int change_position;
4411  wallet->GetChainParams(), options["inputs"], request.params[0],
4412  options["locktime"]);
4413  CCoinControl coin_control;
4414  // Automatically select coins, unless at least one is manually
4415  // selected. Can be overridden by options.add_inputs.
4416  coin_control.m_add_inputs = rawTx.vin.size() == 0;
4417  FundTransaction(pwallet, rawTx, fee, change_position, options,
4418  coin_control);
4419 
4420  bool add_to_wallet = true;
4421  if (options.exists("add_to_wallet")) {
4422  add_to_wallet = options["add_to_wallet"].get_bool();
4423  }
4424 
4425  // Make a blank psbt
4426  PartiallySignedTransaction psbtx(rawTx);
4427 
4428  // Fill transaction with our data and sign
4429  bool complete = true;
4430  const TransactionError err = pwallet->FillPSBT(
4431  psbtx, complete, SigHashType().withForkId(), true, false);
4432  if (err != TransactionError::OK) {
4433  throw JSONRPCTransactionError(err);
4434  }
4435 
4436  CMutableTransaction mtx;
4437  complete = FinalizeAndExtractPSBT(psbtx, mtx);
4438 
4439  UniValue result(UniValue::VOBJ);
4440 
4441  if (psbt_opt_in || !complete || !add_to_wallet) {
4442  // Serialize the PSBT
4444  ssTx << psbtx;
4445  result.pushKV("psbt", EncodeBase64(ssTx.str()));
4446  }
4447 
4448  if (complete) {
4449  std::string err_string;
4450  std::string hex = EncodeHexTx(CTransaction(mtx));
4451  CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
4452  result.pushKV("txid", tx->GetHash().GetHex());
4453  if (add_to_wallet && !psbt_opt_in) {
4454  pwallet->CommitTransaction(tx, {}, {} /* orderForm */);
4455  } else {
4456  result.pushKV("hex", hex);
4457  }
4458  }
4459  result.pushKV("complete", complete);
4460 
4461  return result;
4462  }};
4463 }
4464 
4466  return RPCHelpMan{
4467  "sethdseed",
4468  "Set or generate a new HD wallet seed. Non-HD wallets will not be "
4469  "upgraded to being a HD wallet. Wallets that are already\n"
4470  "HD will have a new HD seed set so that new keys added to the keypool "
4471  "will be derived from this new seed.\n"
4472  "\nNote that you will need to MAKE A NEW BACKUP of your wallet after "
4473  "setting the HD wallet seed.\n" +
4475  {
4476  {"newkeypool", RPCArg::Type::BOOL, RPCArg::Default{true},
4477  "Whether to flush old unused addresses, including change "
4478  "addresses, from the keypool and regenerate it.\n"
4479  " If true, the next address from "
4480  "getnewaddress and change address from getrawchangeaddress will "
4481  "be from this new seed.\n"
4482  " If false, addresses (including "
4483  "change addresses if the wallet already had HD Chain Split "
4484  "enabled) from the existing\n"
4485  " keypool will be used until it has "
4486  "been depleted."},
4487  {"seed", RPCArg::Type::STR, RPCArg::DefaultHint{"random seed"},
4488  "The WIF private key to use as the new HD seed.\n"
4489  " The seed value can be retrieved "
4490  "using the dumpwallet command. It is the private key marked "
4491  "hdseed=1"},
4492  },
4494  RPCExamples{HelpExampleCli("sethdseed", "") +
4495  HelpExampleCli("sethdseed", "false") +
4496  HelpExampleCli("sethdseed", "true \"wifkey\"") +
4497  HelpExampleRpc("sethdseed", "true, \"wifkey\"")},
4498  [&](const RPCHelpMan &self, const Config &config,
4499  const JSONRPCRequest &request) -> UniValue {
4500  std::shared_ptr<CWallet> const wallet =
4501  GetWalletForJSONRPCRequest(request);
4502  if (!wallet) {
4503  return NullUniValue;
4504  }
4505  CWallet *const pwallet = wallet.get();
4506 
4507  LegacyScriptPubKeyMan &spk_man =
4508  EnsureLegacyScriptPubKeyMan(*pwallet, true);
4509 
4512  "Cannot set a HD seed to a wallet with "
4513  "private keys disabled");
4514  }
4515 
4516  LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore);
4517 
4518  // Do not do anything to non-HD wallets
4519  if (!pwallet->CanSupportFeature(FEATURE_HD)) {
4520  throw JSONRPCError(
4522  "Cannot set a HD seed on a non-HD wallet. Use the "
4523  "upgradewallet RPC in order to upgrade a non-HD wallet "
4524  "to HD");
4525  }
4526 
4527  EnsureWalletIsUnlocked(pwallet);
4528 
4529  bool flush_key_pool = true;
4530  if (!request.params[0].isNull()) {
4531  flush_key_pool = request.params[0].get_bool();
4532  }
4533 
4534  CPubKey master_pub_key;
4535  if (request.params[1].isNull()) {
4536  master_pub_key = spk_man.GenerateNewSeed();
4537  } else {
4538  CKey key = DecodeSecret(request.params[1].get_str());
4539  if (!key.IsValid()) {
4541  "Invalid private key");
4542  }
4543 
4544  if (HaveKey(spk_man, key)) {
4545  throw JSONRPCError(
4547  "Already have this key (either as an HD seed or "
4548  "as a loose private key)");
4549  }
4550 
4551  master_pub_key = spk_man.DeriveNewSeed(key);
4552  }
4553 
4554  spk_man.SetHDSeed(master_pub_key);
4555  if (flush_key_pool) {
4556  spk_man.NewKeyPool();
4557  }
4558 
4559  return NullUniValue;
4560  },
4561  };
4562 }
4563 
4565  return RPCHelpMan{
4566  "walletprocesspsbt",
4567  "Update a PSBT with input information from our wallet and then sign "
4568  "inputs that we can sign for." +
4570  {
4572  "The transaction base64 string"},
4573  {"sign", RPCArg::Type::BOOL, RPCArg::Default{true},
4574  "Also sign the transaction when updating"},
4575  {"sighashtype", RPCArg::Type::STR, RPCArg::Default{"ALL|FORKID"},
4576  "The signature hash type to sign with if not specified by "
4577  "the PSBT. Must be one of\n"
4578  " \"ALL|FORKID\"\n"
4579  " \"NONE|FORKID\"\n"
4580  " \"SINGLE|FORKID\"\n"
4581  " \"ALL|FORKID|ANYONECANPAY\"\n"
4582  " \"NONE|FORKID|ANYONECANPAY\"\n"
4583  " \"SINGLE|FORKID|ANYONECANPAY\""},
4584  {"bip32derivs", RPCArg::Type::BOOL, RPCArg::Default{true},
4585  "Includes the BIP 32 derivation paths for public keys if we know "
4586  "them"},
4587  },
4589  "",
4590  "",
4591  {
4592  {RPCResult::Type::STR, "psbt",
4593  "The base64-encoded partially signed transaction"},
4594  {RPCResult::Type::BOOL, "complete",
4595  "If the transaction has a complete set of signatures"},
4596  }},
4597  RPCExamples{HelpExampleCli("walletprocesspsbt", "\"psbt\"")},
4598  [&](const RPCHelpMan &self, const Config &config,
4599  const JSONRPCRequest &request) -> UniValue {
4600  std::shared_ptr<CWallet> const wallet =
4601  GetWalletForJSONRPCRequest(request);
4602  if (!wallet) {
4603  return NullUniValue;
4604  }
4605  const CWallet *const pwallet = wallet.get();
4606 
4607  // Unserialize the transaction
4609  std::string error;
4610  if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
4612  strprintf("TX decode failed %s", error));
4613  }
4614 
4615  // Get the sighash type
4616  SigHashType nHashType = ParseSighashString(request.params[2]);
4617  if (!nHashType.hasForkId()) {
4619  "Signature must use SIGHASH_FORKID");
4620  }
4621 
4622  // Fill transaction with our data and also sign
4623  bool sign = request.params[1].isNull()
4624  ? true
4625  : request.params[1].get_bool();
4626  bool bip32derivs = request.params[3].isNull()
4627  ? true
4628  : request.params[3].get_bool();
4629  bool complete = true;
4630  const TransactionError err = pwallet->FillPSBT(
4631  psbtx, complete, nHashType, sign, bip32derivs);
4632  if (err != TransactionError::OK) {
4633  throw JSONRPCTransactionError(err);
4634  }
4635 
4636  UniValue result(UniValue::VOBJ);
4638  ssTx << psbtx;
4639  result.pushKV("psbt", EncodeBase64(ssTx.str()));
4640  result.pushKV("complete", complete);
4641 
4642  return result;
4643  },
4644  };
4645 }
4646 
4648  const auto &ticker = Currency::get().ticker;
4649  return RPCHelpMan{
4650  "walletcreatefundedpsbt",
4651  "Creates and funds a transaction in the Partially Signed Transaction "
4652  "format.\n"
4653  "Implements the Creator and Updater roles.\n",
4654  {
4655  {
4656  "inputs",
4659  "Leave empty to add inputs automatically. See add_inputs "
4660  "option.",
4661  {
4662  {
4663  "",
4666  "",
4667  {
4668  {"txid", RPCArg::Type::STR_HEX,
4669  RPCArg::Optional::NO, "The transaction id"},
4671  "The output number"},
4672  {"sequence", RPCArg::Type::NUM,
4674  "depends on the value of the 'locktime' and "
4675  "'options.replaceable' arguments"},
4676  "The sequence number"},
4677  },
4678  },
4679  },
4680  },
4681  {"outputs",
4684  "The outputs (key-value pairs), where none of "
4685  "the keys are duplicated.\n"
4686  "That is, each address can only appear once and there can only "
4687  "be one 'data' object.\n"
4688  "For compatibility reasons, a dictionary, which holds the "
4689  "key-value pairs directly, is also\n"
4690  " accepted as second parameter.",
4691  {
4692  {
4693  "",
4696  "",
4697  {
4699  "A key-value pair. The key (string) is the "
4700  "bitcoin address, the value (float or string) is "
4701  "the amount in " +
4702  ticker + ""},
4703  },
4704  },
4705  {
4706  "",
4709  "",
4710  {
4712  "A key-value pair. The key must be \"data\", the "
4713  "value is hex-encoded data"},
4714  },
4715  },
4716  },
4717  RPCArgOptions{.skip_type_check = true}},
4718  {"locktime", RPCArg::Type::NUM, RPCArg::Default{0},
4719  "Raw locktime. Non-0 value also locktime-activates inputs\n"
4720  " Allows this transaction to be "
4721  "replaced by a transaction with higher fees. If provided, it is "
4722  "an error if explicit sequence numbers are incompatible."},
4723  {"options",
4726  "",
4727  {
4728  {"add_inputs", RPCArg::Type::BOOL, RPCArg::Default{false},
4729  "If inputs are specified, automatically include more if they "
4730  "are not enough."},
4731  {"include_unsafe", RPCArg::Type::BOOL, RPCArg::Default{false},
4732  "Include inputs that are not safe to spend (unconfirmed "
4733  "transactions from outside keys).\n"
4734  "Warning: the resulting transaction may become invalid if "
4735  "one of the unsafe inputs disappears.\n"
4736  "If that happens, you will need to fund the transaction with "
4737  "different inputs and republish it."},
4738  {"changeAddress", RPCArg::Type::STR,
4739  RPCArg::DefaultHint{"pool address"},
4740  "The bitcoin address to receive the change"},
4741  {"changePosition", RPCArg::Type::NUM,
4742  RPCArg::DefaultHint{"random"},
4743  "The index of the change output"},
4744  {"includeWatching", RPCArg::Type::BOOL,
4746  "true for watch-only wallets, otherwise false"},
4747  "Also select inputs which are watch only"},
4748  {"lockUnspents", RPCArg::Type::BOOL, RPCArg::Default{false},
4749  "Lock selected unspent outputs"},
4750  {"feeRate", RPCArg::Type::AMOUNT,
4752  "not set: makes wallet determine the fee"},
4753  "Set a specific fee rate in " + ticker + "/kB",
4754  RPCArgOptions{.also_positional = true}},
4755  {
4756  "subtractFeeFromOutputs",
4759  "The outputs to subtract the fee from.\n"
4760  " The fee will be equally "
4761  "deducted from the amount of each specified output.\n"
4762  " Those recipients will "
4763  "receive less bitcoins than you enter in their "
4764  "corresponding amount field.\n"
4765  " If no outputs are "
4766  "specified here, the sender pays the fee.",
4767  {
4768  {"vout_index", RPCArg::Type::NUM,
4770  "The zero-based output index, before a change output "
4771  "is added."},
4772  },
4773  },
4774  },
4775  RPCArgOptions{.oneline_description = "options"}},
4776  {"bip32derivs", RPCArg::Type::BOOL, RPCArg::Default{true},
4777  "Includes the BIP 32 derivation paths for public keys if we know "
4778  "them"},
4779  },
4781  "",
4782  "",
4783  {
4784  {RPCResult::Type::STR, "psbt",
4785  "The resulting raw transaction (base64-encoded string)"},
4787  "Fee in " + ticker + " the resulting transaction pays"},
4788  {RPCResult::Type::NUM, "changepos",
4789  "The position of the added change output, or -1"},
4790  }},
4791  RPCExamples{
4792  "\nCreate a transaction with no inputs\n" +
4793  HelpExampleCli("walletcreatefundedpsbt",
4794  "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" "
4795  "\"[{\\\"data\\\":\\\"00010203\\\"}]\"")},
4796  [&](const RPCHelpMan &self, const Config &config,
4797  const JSONRPCRequest &request) -> UniValue {
4798  std::shared_ptr<CWallet> const wallet =
4799  GetWalletForJSONRPCRequest(request);
4800  if (!wallet) {
4801  return NullUniValue;
4802  }
4803  CWallet *const pwallet = wallet.get();
4804 
4805  Amount fee;
4806  int change_position;
4808  wallet->GetChainParams(), request.params[0], request.params[1],
4809  request.params[2]);
4810  CCoinControl coin_control;
4811  // Automatically select coins, unless at least one is manually
4812  // selected. Can be overridden by options.add_inputs.
4813  coin_control.m_add_inputs = rawTx.vin.size() == 0;
4814  FundTransaction(pwallet, rawTx, fee, change_position,
4815  request.params[3], coin_control);
4816 
4817  // Make a blank psbt
4818  PartiallySignedTransaction psbtx(rawTx);
4819 
4820  // Fill transaction with out data but don't sign
4821  bool bip32derivs = request.params[4].isNull()
4822  ? true
4823  : request.params[4].get_bool();
4824  bool complete = true;
4825  const TransactionError err =
4826  pwallet->FillPSBT(psbtx, complete, SigHashType().withForkId(),
4827  false, bip32derivs);
4828  if (err != TransactionError::OK) {
4829  throw JSONRPCTransactionError(err);
4830  }
4831 
4832  // Serialize the PSBT
4834  ssTx << psbtx;
4835 
4836  UniValue result(UniValue::VOBJ);
4837  result.pushKV("psbt", EncodeBase64(ssTx.str()));
4838  result.pushKV("fee", fee);
4839  result.pushKV("changepos", change_position);
4840  return result;
4841  },
4842  };
4843 }
4844 
4846  return RPCHelpMan{
4847  "upgradewallet",
4848  "Upgrade the wallet. Upgrades to the latest version if no "
4849  "version number is specified\n"
4850  "New keys may be generated and a new wallet backup will need to "
4851  "be made.",
4852  {{"version", RPCArg::Type::NUM, RPCArg::Default{int{FEATURE_LATEST}},
4853  "The version number to upgrade to. Default is the latest "
4854  "wallet version"}},
4856  RPCExamples{HelpExampleCli("upgradewallet", "200300") +
4857  HelpExampleRpc("upgradewallet", "200300")},
4858  [&](const RPCHelpMan &self, const Config &config,
4859  const JSONRPCRequest &request) -> UniValue {
4860  std::shared_ptr<CWallet> const wallet =
4861  GetWalletForJSONRPCRequest(request);
4862  if (!wallet) {
4863  return NullUniValue;
4864  }
4865  CWallet *const pwallet = wallet.get();
4866 
4867  EnsureWalletIsUnlocked(pwallet);
4868 
4869  int version = 0;
4870  if (!request.params[0].isNull()) {
4871  version = request.params[0].getInt<int>();
4872  }
4874  if (!pwallet->UpgradeWallet(version, error)) {
4875  throw JSONRPCError(RPC_WALLET_ERROR, error.original);
4876  }
4877  return error.original;
4878  },
4879  };
4880 }
4881 
4883 
4885  return RPCHelpMan{
4886  "createwallettransaction",
4887  "Create a transaction sending an amount to a given address.\n" +
4889  {
4891  "The bitcoin address to send to."},
4893  "The amount in " + Currency::get().ticker + " to send. eg 0.1"},
4894  },
4895  RPCResult{RPCResult::Type::STR_HEX, "txid", "The transaction id."},
4896  RPCExamples{
4897  HelpExampleCli("createwallettransaction",
4898  "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 100000") +
4899  HelpExampleRpc("createwallettransaction",
4900  "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 100000")},
4901  [&](const RPCHelpMan &self, const Config &config,
4902  const JSONRPCRequest &request) -> UniValue {
4903  std::shared_ptr<CWallet> const wallet =
4904  GetWalletForJSONRPCRequest(request);
4905  if (!wallet) {
4906  return NullUniValue;
4907  }
4908  CWallet *const pwallet = wallet.get();
4909 
4910  // Make sure the results are valid at least up to the most recent
4911  // block the user could have gotten from another RPC command prior
4912  // to now
4913  pwallet->BlockUntilSyncedToCurrentChain();
4914 
4915  LOCK(pwallet->cs_wallet);
4916 
4917  EnsureWalletIsUnlocked(pwallet);
4918 
4919  UniValue address_amounts(UniValue::VOBJ);
4920  const std::string address = request.params[0].get_str();
4921  address_amounts.pushKV(address, request.params[1]);
4922  UniValue subtractFeeFromAmount(UniValue::VARR);
4923 
4924  std::vector<CRecipient> recipients;
4925  ParseRecipients(address_amounts, subtractFeeFromAmount, recipients,
4926  wallet->GetChainParams());
4927 
4928  CCoinControl coin_control;
4929  return SendMoney(pwallet, coin_control, recipients, {}, false);
4930  },
4931  };
4932 }
4933 
4935  // clang-format off
4936  static const CRPCCommand commands[] = {
4937  // category actor (function)
4938  // ------------------ ----------------------
4939  { "rawtransactions", fundrawtransaction, },
4940  { "wallet", abandontransaction, },
4941  { "wallet", addmultisigaddress, },
4942  { "wallet", createwallet, },
4943  { "wallet", getaddressesbylabel, },
4944  { "wallet", getaddressinfo, },
4945  { "wallet", getbalance, },
4946  { "wallet", getnewaddress, },
4947  { "wallet", getrawchangeaddress, },
4948  { "wallet", getreceivedbyaddress, },
4949  { "wallet", getreceivedbylabel, },
4950  { "wallet", gettransaction, },
4951  { "wallet", getunconfirmedbalance, },
4952  { "wallet", getbalances, },
4953  { "wallet", getwalletinfo, },
4954  { "wallet", keypoolrefill, },
4955  { "wallet", listaddressgroupings, },
4956  { "wallet", listlabels, },
4957  { "wallet", listlockunspent, },
4958  { "wallet", listreceivedbyaddress, },
4959  { "wallet", listreceivedbylabel, },
4960  { "wallet", listsinceblock, },
4961  { "wallet", listtransactions, },
4962  { "wallet", listunspent, },
4963  { "wallet", listwalletdir, },
4964  { "wallet", listwallets, },
4965  { "wallet", loadwallet, },
4966  { "wallet", lockunspent, },
4967  { "wallet", rescanblockchain, },
4968  { "wallet", send, },
4969  { "wallet", sendmany, },
4970  { "wallet", sendtoaddress, },
4971  { "wallet", sethdseed, },
4972  { "wallet", setlabel, },
4973  { "wallet", settxfee, },
4974  { "wallet", setwalletflag, },
4975  { "wallet", signmessage, },
4976  { "wallet", signrawtransactionwithwallet, },
4977  { "wallet", unloadwallet, },
4978  { "wallet", upgradewallet, },
4979  { "wallet", walletcreatefundedpsbt, },
4980  { "wallet", walletprocesspsbt, },
4981  // For testing purpose
4982  { "hidden", createwallettransaction, },
4983  };
4984  // clang-format on
4985 
4986  return commands;
4987 }
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:3823
UniValue operator()(const PKHash &pkhash) const
Definition: rpcwallet.cpp:3870
UniValue operator()(const ScriptHash &scripthash) const
Definition: rpcwallet.cpp:3881
void ProcessSubScript(const CScript &subscript, UniValue &obj) const
Definition: rpcwallet.cpp:3825
DescribeWalletAddressVisitor(const SigningProvider *_provider)
Definition: rpcwallet.cpp:3863
UniValue operator()(const CNoDestination &dest) const
Definition: rpcwallet.cpp:3866
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
void push_back(UniValue val)
Definition: univalue.cpp:96
const std::string & get_str() const
const UniValue & find_value(std::string_view key) const
Definition: univalue.cpp:229
@ VNULL
Definition: univalue.h:30
@ VOBJ
Definition: univalue.h:31
@ VSTR
Definition: univalue.h:33
@ VARR
Definition: univalue.h:32
@ VNUM
Definition: univalue.h:34
@ VBOOL
Definition: univalue.h:35
bool isNull() const
Definition: univalue.h:104
const UniValue & get_obj() const
size_t size() const
Definition: univalue.h:92
enum VType type() const
Definition: univalue.h:147
void pushKVs(UniValue obj)
Definition: univalue.cpp:126
const std::vector< std::string > & getKeys() const
bool empty() const
Definition: univalue.h:90
void pushKVEnd(std::string key, UniValue val)
Definition: univalue.cpp:108
Int getInt() const
Definition: univalue.h:157
const UniValue & get_array() const
bool exists(const std::string &key) const
Definition: univalue.h:99
void reserve(size_t n)
Definition: univalue.h:68
void pushKV(std::string key, UniValue val)
Definition: univalue.cpp:115
bool get_bool() 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:226
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:402
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:487
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:150
CTxDestination AddAndGetMultisigDestination(const int required, const std::vector< CPubKey > &pubkeys, OutputType type, FillableSigningProvider &keystore, CScript &script_out)
Definition: util.cpp:233
std::string HelpExampleRpcNamed(const std::string &methodname, const RPCArgList &args)
Definition: util.cpp:176
UniValue JSONRPCTransactionError(TransactionError terr, const std::string &err_string)
Definition: util.cpp:333
Amount AmountFromValue(const UniValue &value)
Definition: util.cpp:55
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:167
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:191
CPubKey AddrToPubKey(const CChainParams &chainparams, const FillableSigningProvider &keystore, const std::string &addr_in)
Definition: util.cpp:205
uint256 ParseHashO(const UniValue &o, std::string strKey)
Definition: util.cpp:90
uint256 ParseHashV(const UniValue &v, std::string strName)
Utilities: convert hex-encoded values (throws error if not hex).
Definition: util.cpp:73
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:26
std::string HelpExampleCliNamed(const std::string &methodname, const RPCArgList &args)
Definition: util.cpp:155
UniValue DescribeAddress(const CTxDestination &dest)
Definition: util.cpp:301
static RPCHelpMan createwallet()
Definition: rpcwallet.cpp:2801
static RPCHelpMan getnewaddress()
Definition: rpcwallet.cpp:95
static RPCHelpMan sethdseed()
Definition: rpcwallet.cpp:4465
static RPCHelpMan listreceivedbylabel()
Definition: rpcwallet.cpp:1216
static RPCHelpMan sendtoaddress()
Definition: rpcwallet.cpp:316
static RPCHelpMan listunspent()
Definition: rpcwallet.cpp:2981
static RPCHelpMan getrawchangeaddress()
Definition: rpcwallet.cpp:159
RPCHelpMan listlabels()
Definition: rpcwallet.cpp:4157
static RPCHelpMan walletprocesspsbt()
Definition: rpcwallet.cpp:4564
static void ListTransactions(const CWallet *const pwallet, const CWalletTx &wtx, int nMinDepth, bool fLong, Vec &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:1296
static RPCHelpMan fundrawtransaction()
Definition: rpcwallet.cpp:3436
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:3907
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:4088
static RPCHelpMan listlockunspent()
Definition: rpcwallet.cpp:2252
static RPCHelpMan send()
Definition: rpcwallet.cpp:4219
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:2645
RPCHelpMan rescanblockchain()
Definition: rpcwallet.cpp:3711
static RPCHelpMan upgradewallet()
Definition: rpcwallet.cpp:4845
static RPCHelpMan unloadwallet()
Definition: rpcwallet.cpp:2914
static RPCHelpMan walletcreatefundedpsbt()
Definition: rpcwallet.cpp:4647
static RPCHelpMan getbalances()
Definition: rpcwallet.cpp:2373
static RPCHelpMan listwalletdir()
Definition: rpcwallet.cpp:2605
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:3917
static RPCHelpMan getwalletinfo()
Definition: rpcwallet.cpp:2468
static RPCHelpMan lockunspent()
Definition: rpcwallet.cpp:2086
Span< const CRPCCommand > GetWalletRPCCommands()
Definition: rpcwallet.cpp:4934
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:2717
RPCHelpMan signrawtransactionwithwallet()
Definition: rpcwallet.cpp:3580
static RPCHelpMan createwallettransaction()
Definition: rpcwallet.cpp:4884
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:1379
static RPCHelpMan loadwallet()
Definition: rpcwallet.cpp:2673
static RPCHelpMan listsinceblock()
Definition: rpcwallet.cpp:1574
static RPCHelpMan settxfee()
Definition: rpcwallet.cpp:2319
static RPCHelpMan listreceivedbyaddress()
Definition: rpcwallet.cpp:1138
static RPCHelpMan sendmany()
Definition: rpcwallet.cpp:739
RPCHelpMan listtransactions()
Definition: rpcwallet.cpp:1415
static UniValue DescribeWalletAddress(const CWallet *const pwallet, const CTxDestination &dest)
Definition: rpcwallet.cpp:3892
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:3281
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:53
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:86
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)
@ OBJ_NAMED_PARAMS
Special type that behaves almost exactly like OBJ, defining an options object with a list of pre-defi...
std::string DefaultHint
Hint for default value.
Definition: util.h:195
@ OMITTED
The arg is optional for one of two reasons:
@ NO
Required arg.
std::string oneline_description
Should be empty unless it is supposed to override the auto-generated summary line.
Definition: util.h:128
bool also_positional
If set allows a named-parameter field in an OBJ_NAMED_PARAM options object to have the same name as a...
Definition: util.h:147
bool skip_type_check
Definition: util.h:125
@ 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:16
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