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