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