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