Bitcoin Core  24.99.0
P2P Digital Currency
coins.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2022 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <core_io.h>
6 #include <hash.h>
7 #include <key_io.h>
8 #include <rpc/util.h>
9 #include <util/moneystr.h>
10 #include <wallet/coincontrol.h>
11 #include <wallet/receive.h>
12 #include <wallet/rpc/util.h>
13 #include <wallet/spend.h>
14 #include <wallet/wallet.h>
15 
16 #include <univalue.h>
17 
18 
19 namespace wallet {
20 static CAmount GetReceived(const CWallet& wallet, const UniValue& params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
21 {
22  std::vector<CTxDestination> addresses;
23  if (by_label) {
24  // Get the set of addresses assigned to label
25  addresses = wallet.ListAddrBookAddresses(CWallet::AddrBookFilter{LabelFromValue(params[0])});
26  if (addresses.empty()) throw JSONRPCError(RPC_WALLET_ERROR, "Label not found in wallet");
27  } else {
28  // Get the address
29  CTxDestination dest = DecodeDestination(params[0].get_str());
30  if (!IsValidDestination(dest)) {
31  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
32  }
33  addresses.emplace_back(dest);
34  }
35 
36  // Filter by own scripts only
37  std::set<CScript> output_scripts;
38  for (const auto& address : addresses) {
39  auto output_script{GetScriptForDestination(address)};
40  if (wallet.IsMine(output_script)) {
41  output_scripts.insert(output_script);
42  }
43  }
44 
45  if (output_scripts.empty()) {
46  throw JSONRPCError(RPC_WALLET_ERROR, "Address not found in wallet");
47  }
48 
49  // Minimum confirmations
50  int min_depth = 1;
51  if (!params[1].isNull())
52  min_depth = params[1].getInt<int>();
53 
54  const bool include_immature_coinbase{params[2].isNull() ? false : params[2].get_bool()};
55 
56  // Tally
57  CAmount amount = 0;
58  for (const std::pair<const uint256, CWalletTx>& wtx_pair : wallet.mapWallet) {
59  const CWalletTx& wtx = wtx_pair.second;
60  int depth{wallet.GetTxDepthInMainChain(wtx)};
61  if (depth < min_depth
62  // Coinbase with less than 1 confirmation is no longer in the main chain
63  || (wtx.IsCoinBase() && (depth < 1))
64  || (wallet.IsTxImmatureCoinBase(wtx) && !include_immature_coinbase))
65  {
66  continue;
67  }
68 
69  for (const CTxOut& txout : wtx.tx->vout) {
70  if (output_scripts.count(txout.scriptPubKey) > 0) {
71  amount += txout.nValue;
72  }
73  }
74  }
75 
76  return amount;
77 }
78 
79 
81 {
82  return RPCHelpMan{"getreceivedbyaddress",
83  "\nReturns the total amount received by the given address in transactions with at least minconf confirmations.\n",
84  {
85  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address for transactions."},
86  {"minconf", RPCArg::Type::NUM, RPCArg::Default{1}, "Only include transactions confirmed at least this many times."},
87  {"include_immature_coinbase", RPCArg::Type::BOOL, RPCArg::Default{false}, "Include immature coinbase transactions."},
88  },
89  RPCResult{
90  RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " received at this address."
91  },
93  "\nThe amount from transactions with at least 1 confirmation\n"
94  + HelpExampleCli("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\"") +
95  "\nThe amount including unconfirmed transactions, zero confirmations\n"
96  + HelpExampleCli("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0") +
97  "\nThe amount with at least 6 confirmations\n"
98  + HelpExampleCli("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 6") +
99  "\nThe amount with at least 6 confirmations including immature coinbase outputs\n"
100  + HelpExampleCli("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 6 true") +
101  "\nAs a JSON-RPC call\n"
102  + HelpExampleRpc("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\", 6")
103  },
104  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
105 {
106  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
107  if (!pwallet) return UniValue::VNULL;
108 
109  // Make sure the results are valid at least up to the most recent block
110  // the user could have gotten from another RPC command prior to now
111  pwallet->BlockUntilSyncedToCurrentChain();
112 
113  LOCK(pwallet->cs_wallet);
114 
115  return ValueFromAmount(GetReceived(*pwallet, request.params, /*by_label=*/false));
116 },
117  };
118 }
119 
120 
122 {
123  return RPCHelpMan{"getreceivedbylabel",
124  "\nReturns the total amount received by addresses with <label> in transactions with at least [minconf] confirmations.\n",
125  {
126  {"label", RPCArg::Type::STR, RPCArg::Optional::NO, "The selected label, may be the default label using \"\"."},
127  {"minconf", RPCArg::Type::NUM, RPCArg::Default{1}, "Only include transactions confirmed at least this many times."},
128  {"include_immature_coinbase", RPCArg::Type::BOOL, RPCArg::Default{false}, "Include immature coinbase transactions."},
129  },
130  RPCResult{
131  RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " received for this label."
132  },
133  RPCExamples{
134  "\nAmount received by the default label with at least 1 confirmation\n"
135  + HelpExampleCli("getreceivedbylabel", "\"\"") +
136  "\nAmount received at the tabby label including unconfirmed amounts with zero confirmations\n"
137  + HelpExampleCli("getreceivedbylabel", "\"tabby\" 0") +
138  "\nThe amount with at least 6 confirmations\n"
139  + HelpExampleCli("getreceivedbylabel", "\"tabby\" 6") +
140  "\nThe amount with at least 6 confirmations including immature coinbase outputs\n"
141  + HelpExampleCli("getreceivedbylabel", "\"tabby\" 6 true") +
142  "\nAs a JSON-RPC call\n"
143  + HelpExampleRpc("getreceivedbylabel", "\"tabby\", 6, true")
144  },
145  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
146 {
147  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
148  if (!pwallet) return UniValue::VNULL;
149 
150  // Make sure the results are valid at least up to the most recent block
151  // the user could have gotten from another RPC command prior to now
152  pwallet->BlockUntilSyncedToCurrentChain();
153 
154  LOCK(pwallet->cs_wallet);
155 
156  return ValueFromAmount(GetReceived(*pwallet, request.params, /*by_label=*/true));
157 },
158  };
159 }
160 
161 
163 {
164  return RPCHelpMan{"getbalance",
165  "\nReturns the total available balance.\n"
166  "The available balance is what the wallet considers currently spendable, and is\n"
167  "thus affected by options which limit spendability such as -spendzeroconfchange.\n",
168  {
169  {"dummy", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Remains for backward compatibility. Must be excluded or set to \"*\"."},
170  {"minconf", RPCArg::Type::NUM, RPCArg::Default{0}, "Only include transactions confirmed at least this many times."},
171  {"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also include balance in watch-only addresses (see 'importaddress')"},
172  {"avoid_reuse", RPCArg::Type::BOOL, RPCArg::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."},
173  },
174  RPCResult{
175  RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " received for this wallet."
176  },
177  RPCExamples{
178  "\nThe total amount in the wallet with 0 or more confirmations\n"
179  + HelpExampleCli("getbalance", "") +
180  "\nThe total amount in the wallet with at least 6 confirmations\n"
181  + HelpExampleCli("getbalance", "\"*\" 6") +
182  "\nAs a JSON-RPC call\n"
183  + HelpExampleRpc("getbalance", "\"*\", 6")
184  },
185  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
186 {
187  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
188  if (!pwallet) return UniValue::VNULL;
189 
190  // Make sure the results are valid at least up to the most recent block
191  // the user could have gotten from another RPC command prior to now
192  pwallet->BlockUntilSyncedToCurrentChain();
193 
194  LOCK(pwallet->cs_wallet);
195 
196  const UniValue& dummy_value = request.params[0];
197  if (!dummy_value.isNull() && dummy_value.get_str() != "*") {
198  throw JSONRPCError(RPC_METHOD_DEPRECATED, "dummy first argument must be excluded or set to \"*\".");
199  }
200 
201  int min_depth = 0;
202  if (!request.params[1].isNull()) {
203  min_depth = request.params[1].getInt<int>();
204  }
205 
206  bool include_watchonly = ParseIncludeWatchonly(request.params[2], *pwallet);
207 
208  bool avoid_reuse = GetAvoidReuseFlag(*pwallet, request.params[3]);
209 
210  const auto bal = GetBalance(*pwallet, min_depth, avoid_reuse);
211 
212  return ValueFromAmount(bal.m_mine_trusted + (include_watchonly ? bal.m_watchonly_trusted : 0));
213 },
214  };
215 }
216 
218 {
219  return RPCHelpMan{"getunconfirmedbalance",
220  "DEPRECATED\nIdentical to getbalances().mine.untrusted_pending\n",
221  {},
222  RPCResult{RPCResult::Type::NUM, "", "The balance"},
223  RPCExamples{""},
224  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
225 {
226  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
227  if (!pwallet) return UniValue::VNULL;
228 
229  // Make sure the results are valid at least up to the most recent block
230  // the user could have gotten from another RPC command prior to now
231  pwallet->BlockUntilSyncedToCurrentChain();
232 
233  LOCK(pwallet->cs_wallet);
234 
236 },
237  };
238 }
239 
241 {
242  return RPCHelpMan{"lockunspent",
243  "\nUpdates list of temporarily unspendable outputs.\n"
244  "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
245  "If no transaction outputs are specified when unlocking then all current locked transaction outputs are unlocked.\n"
246  "A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n"
247  "Manually selected coins are automatically unlocked.\n"
248  "Locks are stored in memory only, unless persistent=true, in which case they will be written to the\n"
249  "wallet database and loaded on node start. Unwritten (persistent=false) locks are always cleared\n"
250  "(by virtue of process exit) when a node stops or fails. Unlocking will clear both persistent and not.\n"
251  "Also see the listunspent call\n",
252  {
253  {"unlock", RPCArg::Type::BOOL, RPCArg::Optional::NO, "Whether to unlock (true) or lock (false) the specified transactions"},
254  {"transactions", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "The transaction outputs and within each, the txid (string) vout (numeric).",
255  {
257  {
258  {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
259  {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
260  },
261  },
262  },
263  },
264  {"persistent", RPCArg::Type::BOOL, RPCArg::Default{false}, "Whether to write/erase this lock in the wallet database, or keep the change in memory only. Ignored for unlocking."},
265  },
266  RPCResult{
267  RPCResult::Type::BOOL, "", "Whether the command was successful or not"
268  },
269  RPCExamples{
270  "\nList the unspent transactions\n"
271  + HelpExampleCli("listunspent", "") +
272  "\nLock an unspent transaction\n"
273  + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
274  "\nList the locked transactions\n"
275  + HelpExampleCli("listlockunspent", "") +
276  "\nUnlock the transaction again\n"
277  + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
278  "\nLock the transaction persistently in the wallet database\n"
279  + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\" true") +
280  "\nAs a JSON-RPC call\n"
281  + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
282  },
283  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
284 {
285  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
286  if (!pwallet) return UniValue::VNULL;
287 
288  // Make sure the results are valid at least up to the most recent block
289  // the user could have gotten from another RPC command prior to now
290  pwallet->BlockUntilSyncedToCurrentChain();
291 
292  LOCK(pwallet->cs_wallet);
293 
294  bool fUnlock = request.params[0].get_bool();
295 
296  const bool persistent{request.params[2].isNull() ? false : request.params[2].get_bool()};
297 
298  if (request.params[1].isNull()) {
299  if (fUnlock) {
300  if (!pwallet->UnlockAllCoins())
301  throw JSONRPCError(RPC_WALLET_ERROR, "Unlocking coins failed");
302  }
303  return true;
304  }
305 
306  const UniValue& output_params = request.params[1].get_array();
307 
308  // Create and validate the COutPoints first.
309 
310  std::vector<COutPoint> outputs;
311  outputs.reserve(output_params.size());
312 
313  for (unsigned int idx = 0; idx < output_params.size(); idx++) {
314  const UniValue& o = output_params[idx].get_obj();
315 
316  RPCTypeCheckObj(o,
317  {
318  {"txid", UniValueType(UniValue::VSTR)},
319  {"vout", UniValueType(UniValue::VNUM)},
320  });
321 
322  const uint256 txid(ParseHashO(o, "txid"));
323  const int nOutput = find_value(o, "vout").getInt<int>();
324  if (nOutput < 0) {
325  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout cannot be negative");
326  }
327 
328  const COutPoint outpt(txid, nOutput);
329 
330  const auto it = pwallet->mapWallet.find(outpt.hash);
331  if (it == pwallet->mapWallet.end()) {
332  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, unknown transaction");
333  }
334 
335  const CWalletTx& trans = it->second;
336 
337  if (outpt.n >= trans.tx->vout.size()) {
338  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout index out of bounds");
339  }
340 
341  if (pwallet->IsSpent(outpt)) {
342  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected unspent output");
343  }
344 
345  const bool is_locked = pwallet->IsLockedCoin(outpt);
346 
347  if (fUnlock && !is_locked) {
348  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected locked output");
349  }
350 
351  if (!fUnlock && is_locked && !persistent) {
352  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, output already locked");
353  }
354 
355  outputs.push_back(outpt);
356  }
357 
358  std::unique_ptr<WalletBatch> batch = nullptr;
359  // Unlock is always persistent
360  if (fUnlock || persistent) batch = std::make_unique<WalletBatch>(pwallet->GetDatabase());
361 
362  // Atomically set (un)locked status for the outputs.
363  for (const COutPoint& outpt : outputs) {
364  if (fUnlock) {
365  if (!pwallet->UnlockCoin(outpt, batch.get())) throw JSONRPCError(RPC_WALLET_ERROR, "Unlocking coin failed");
366  } else {
367  if (!pwallet->LockCoin(outpt, batch.get())) throw JSONRPCError(RPC_WALLET_ERROR, "Locking coin failed");
368  }
369  }
370 
371  return true;
372 },
373  };
374 }
375 
377 {
378  return RPCHelpMan{"listlockunspent",
379  "\nReturns list of temporarily unspendable outputs.\n"
380  "See the lockunspent call to lock and unlock transactions for spending.\n",
381  {},
382  RPCResult{
383  RPCResult::Type::ARR, "", "",
384  {
385  {RPCResult::Type::OBJ, "", "",
386  {
387  {RPCResult::Type::STR_HEX, "txid", "The transaction id locked"},
388  {RPCResult::Type::NUM, "vout", "The vout value"},
389  }},
390  }
391  },
392  RPCExamples{
393  "\nList the unspent transactions\n"
394  + HelpExampleCli("listunspent", "") +
395  "\nLock an unspent transaction\n"
396  + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
397  "\nList the locked transactions\n"
398  + HelpExampleCli("listlockunspent", "") +
399  "\nUnlock the transaction again\n"
400  + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
401  "\nAs a JSON-RPC call\n"
402  + HelpExampleRpc("listlockunspent", "")
403  },
404  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
405 {
406  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
407  if (!pwallet) return UniValue::VNULL;
408 
409  LOCK(pwallet->cs_wallet);
410 
411  std::vector<COutPoint> vOutpts;
412  pwallet->ListLockedCoins(vOutpts);
413 
415 
416  for (const COutPoint& outpt : vOutpts) {
418 
419  o.pushKV("txid", outpt.hash.GetHex());
420  o.pushKV("vout", (int)outpt.n);
421  ret.push_back(o);
422  }
423 
424  return ret;
425 },
426  };
427 }
428 
430 {
431  return RPCHelpMan{
432  "getbalances",
433  "Returns an object with all balances in " + CURRENCY_UNIT + ".\n",
434  {},
435  RPCResult{
436  RPCResult::Type::OBJ, "", "",
437  {
438  {RPCResult::Type::OBJ, "mine", "balances from outputs that the wallet can sign",
439  {
440  {RPCResult::Type::STR_AMOUNT, "trusted", "trusted balance (outputs created by the wallet or confirmed outputs)"},
441  {RPCResult::Type::STR_AMOUNT, "untrusted_pending", "untrusted pending balance (outputs created by others that are in the mempool)"},
442  {RPCResult::Type::STR_AMOUNT, "immature", "balance from immature coinbase outputs"},
443  {RPCResult::Type::STR_AMOUNT, "used", /*optional=*/true, "(only present if avoid_reuse is set) balance from coins sent to addresses that were previously spent from (potentially privacy violating)"},
444  }},
445  {RPCResult::Type::OBJ, "watchonly", /*optional=*/true, "watchonly balances (not present if wallet does not watch anything)",
446  {
447  {RPCResult::Type::STR_AMOUNT, "trusted", "trusted balance (outputs created by the wallet or confirmed outputs)"},
448  {RPCResult::Type::STR_AMOUNT, "untrusted_pending", "untrusted pending balance (outputs created by others that are in the mempool)"},
449  {RPCResult::Type::STR_AMOUNT, "immature", "balance from immature coinbase outputs"},
450  }},
451  }
452  },
453  RPCExamples{
454  HelpExampleCli("getbalances", "") +
455  HelpExampleRpc("getbalances", "")},
456  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
457 {
458  const std::shared_ptr<const CWallet> rpc_wallet = GetWalletForJSONRPCRequest(request);
459  if (!rpc_wallet) return UniValue::VNULL;
460  const CWallet& wallet = *rpc_wallet;
461 
462  // Make sure the results are valid at least up to the most recent block
463  // the user could have gotten from another RPC command prior to now
464  wallet.BlockUntilSyncedToCurrentChain();
465 
466  LOCK(wallet.cs_wallet);
467 
468  const auto bal = GetBalance(wallet);
469  UniValue balances{UniValue::VOBJ};
470  {
471  UniValue balances_mine{UniValue::VOBJ};
472  balances_mine.pushKV("trusted", ValueFromAmount(bal.m_mine_trusted));
473  balances_mine.pushKV("untrusted_pending", ValueFromAmount(bal.m_mine_untrusted_pending));
474  balances_mine.pushKV("immature", ValueFromAmount(bal.m_mine_immature));
475  if (wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE)) {
476  // If the AVOID_REUSE flag is set, bal has been set to just the un-reused address balance. Get
477  // the total balance, and then subtract bal to get the reused address balance.
478  const auto full_bal = GetBalance(wallet, 0, false);
479  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));
480  }
481  balances.pushKV("mine", balances_mine);
482  }
483  auto spk_man = wallet.GetLegacyScriptPubKeyMan();
484  if (spk_man && spk_man->HaveWatchOnly()) {
485  UniValue balances_watchonly{UniValue::VOBJ};
486  balances_watchonly.pushKV("trusted", ValueFromAmount(bal.m_watchonly_trusted));
487  balances_watchonly.pushKV("untrusted_pending", ValueFromAmount(bal.m_watchonly_untrusted_pending));
488  balances_watchonly.pushKV("immature", ValueFromAmount(bal.m_watchonly_immature));
489  balances.pushKV("watchonly", balances_watchonly);
490  }
491  return balances;
492 },
493  };
494 }
495 
497 {
498  return RPCHelpMan{
499  "listunspent",
500  "\nReturns array of unspent transaction outputs\n"
501  "with between minconf and maxconf (inclusive) confirmations.\n"
502  "Optionally filter to only include txouts paid to specified addresses.\n",
503  {
504  {"minconf", RPCArg::Type::NUM, RPCArg::Default{1}, "The minimum confirmations to filter"},
505  {"maxconf", RPCArg::Type::NUM, RPCArg::Default{9999999}, "The maximum confirmations to filter"},
506  {"addresses", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "The bitcoin addresses to filter",
507  {
508  {"address", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "bitcoin address"},
509  },
510  },
511  {"include_unsafe", RPCArg::Type::BOOL, RPCArg::Default{true}, "Include outputs that are not safe to spend\n"
512  "See description of \"safe\" attribute below."},
513  {"query_options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "JSON with query options",
514  {
515  {"minimumAmount", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(0)}, "Minimum value of each UTXO in " + CURRENCY_UNIT + ""},
516  {"maximumAmount", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"unlimited"}, "Maximum value of each UTXO in " + CURRENCY_UNIT + ""},
517  {"maximumCount", RPCArg::Type::NUM, RPCArg::DefaultHint{"unlimited"}, "Maximum number of UTXOs"},
518  {"minimumSumAmount", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"unlimited"}, "Minimum sum value of all UTXOs in " + CURRENCY_UNIT + ""},
519  {"include_immature_coinbase", RPCArg::Type::BOOL, RPCArg::Default{false}, "Include immature coinbase UTXOs"}
520  },
521  RPCArgOptions{.oneline_description="query_options"}},
522  },
523  RPCResult{
524  RPCResult::Type::ARR, "", "",
525  {
526  {RPCResult::Type::OBJ, "", "",
527  {
528  {RPCResult::Type::STR_HEX, "txid", "the transaction id"},
529  {RPCResult::Type::NUM, "vout", "the vout value"},
530  {RPCResult::Type::STR, "address", /*optional=*/true, "the bitcoin address"},
531  {RPCResult::Type::STR, "label", /*optional=*/true, "The associated label, or \"\" for the default label"},
532  {RPCResult::Type::STR, "scriptPubKey", "the script key"},
533  {RPCResult::Type::STR_AMOUNT, "amount", "the transaction output amount in " + CURRENCY_UNIT},
534  {RPCResult::Type::NUM, "confirmations", "The number of confirmations"},
535  {RPCResult::Type::NUM, "ancestorcount", /*optional=*/true, "The number of in-mempool ancestor transactions, including this one (if transaction is in the mempool)"},
536  {RPCResult::Type::NUM, "ancestorsize", /*optional=*/true, "The virtual transaction size of in-mempool ancestors, including this one (if transaction is in the mempool)"},
537  {RPCResult::Type::STR_AMOUNT, "ancestorfees", /*optional=*/true, "The total fees of in-mempool ancestors (including this one) with fee deltas used for mining priority in " + CURRENCY_ATOM + " (if transaction is in the mempool)"},
538  {RPCResult::Type::STR_HEX, "redeemScript", /*optional=*/true, "The redeemScript if scriptPubKey is P2SH"},
539  {RPCResult::Type::STR, "witnessScript", /*optional=*/true, "witnessScript if the scriptPubKey is P2WSH or P2SH-P2WSH"},
540  {RPCResult::Type::BOOL, "spendable", "Whether we have the private keys to spend this output"},
541  {RPCResult::Type::BOOL, "solvable", "Whether we know how to spend this output, ignoring the lack of keys"},
542  {RPCResult::Type::BOOL, "reused", /*optional=*/true, "(only present if avoid_reuse is set) Whether this output is reused/dirty (sent to an address that was previously spent from)"},
543  {RPCResult::Type::STR, "desc", /*optional=*/true, "(only when solvable) A descriptor for spending this output"},
544  {RPCResult::Type::ARR, "parent_descs", /*optional=*/false, "List of parent descriptors for the scriptPubKey of this coin.", {
545  {RPCResult::Type::STR, "desc", "The descriptor string."},
546  }},
547  {RPCResult::Type::BOOL, "safe", "Whether this output is considered safe to spend. Unconfirmed transactions\n"
548  "from outside keys and unconfirmed replacement transactions are considered unsafe\n"
549  "and are not eligible for spending by fundrawtransaction and sendtoaddress."},
550  }},
551  }
552  },
553  RPCExamples{
554  HelpExampleCli("listunspent", "")
555  + HelpExampleCli("listunspent", "6 9999999 \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"")
556  + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"")
557  + HelpExampleCli("listunspent", "6 9999999 '[]' true '{ \"minimumAmount\": 0.005 }'")
558  + HelpExampleRpc("listunspent", "6, 9999999, [] , true, { \"minimumAmount\": 0.005 } ")
559  },
560  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
561 {
562  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
563  if (!pwallet) return UniValue::VNULL;
564 
565  int nMinDepth = 1;
566  if (!request.params[0].isNull()) {
567  nMinDepth = request.params[0].getInt<int>();
568  }
569 
570  int nMaxDepth = 9999999;
571  if (!request.params[1].isNull()) {
572  nMaxDepth = request.params[1].getInt<int>();
573  }
574 
575  std::set<CTxDestination> destinations;
576  if (!request.params[2].isNull()) {
577  UniValue inputs = request.params[2].get_array();
578  for (unsigned int idx = 0; idx < inputs.size(); idx++) {
579  const UniValue& input = inputs[idx];
580  CTxDestination dest = DecodeDestination(input.get_str());
581  if (!IsValidDestination(dest)) {
582  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + input.get_str());
583  }
584  if (!destinations.insert(dest).second) {
585  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + input.get_str());
586  }
587  }
588  }
589 
590  bool include_unsafe = true;
591  if (!request.params[3].isNull()) {
592  include_unsafe = request.params[3].get_bool();
593  }
594 
595  CoinFilterParams filter_coins;
596  filter_coins.min_amount = 0;
597 
598  if (!request.params[4].isNull()) {
599  const UniValue& options = request.params[4].get_obj();
600 
601  RPCTypeCheckObj(options,
602  {
603  {"minimumAmount", UniValueType()},
604  {"maximumAmount", UniValueType()},
605  {"minimumSumAmount", UniValueType()},
606  {"maximumCount", UniValueType(UniValue::VNUM)},
607  {"include_immature_coinbase", UniValueType(UniValue::VBOOL)}
608  },
609  true, true);
610 
611  if (options.exists("minimumAmount"))
612  filter_coins.min_amount = AmountFromValue(options["minimumAmount"]);
613 
614  if (options.exists("maximumAmount"))
615  filter_coins.max_amount = AmountFromValue(options["maximumAmount"]);
616 
617  if (options.exists("minimumSumAmount"))
618  filter_coins.min_sum_amount = AmountFromValue(options["minimumSumAmount"]);
619 
620  if (options.exists("maximumCount"))
621  filter_coins.max_count = options["maximumCount"].getInt<int64_t>();
622 
623  if (options.exists("include_immature_coinbase")) {
624  filter_coins.include_immature_coinbase = options["include_immature_coinbase"].get_bool();
625  }
626  }
627 
628  // Make sure the results are valid at least up to the most recent block
629  // the user could have gotten from another RPC command prior to now
630  pwallet->BlockUntilSyncedToCurrentChain();
631 
632  UniValue results(UniValue::VARR);
633  std::vector<COutput> vecOutputs;
634  {
635  CCoinControl cctl;
636  cctl.m_avoid_address_reuse = false;
637  cctl.m_min_depth = nMinDepth;
638  cctl.m_max_depth = nMaxDepth;
639  cctl.m_include_unsafe_inputs = include_unsafe;
640  LOCK(pwallet->cs_wallet);
641  vecOutputs = AvailableCoinsListUnspent(*pwallet, &cctl, filter_coins).All();
642  }
643 
644  LOCK(pwallet->cs_wallet);
645 
646  const bool avoid_reuse = pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE);
647 
648  for (const COutput& out : vecOutputs) {
649  CTxDestination address;
650  const CScript& scriptPubKey = out.txout.scriptPubKey;
651  bool fValidAddress = ExtractDestination(scriptPubKey, address);
652  bool reused = avoid_reuse && pwallet->IsSpentKey(scriptPubKey);
653 
654  if (destinations.size() && (!fValidAddress || !destinations.count(address)))
655  continue;
656 
657  UniValue entry(UniValue::VOBJ);
658  entry.pushKV("txid", out.outpoint.hash.GetHex());
659  entry.pushKV("vout", (int)out.outpoint.n);
660 
661  if (fValidAddress) {
662  entry.pushKV("address", EncodeDestination(address));
663 
664  const auto* address_book_entry = pwallet->FindAddressBookEntry(address);
665  if (address_book_entry) {
666  entry.pushKV("label", address_book_entry->GetLabel());
667  }
668 
669  std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);
670  if (provider) {
671  if (scriptPubKey.IsPayToScriptHash()) {
672  const CScriptID& hash = CScriptID(std::get<ScriptHash>(address));
673  CScript redeemScript;
674  if (provider->GetCScript(hash, redeemScript)) {
675  entry.pushKV("redeemScript", HexStr(redeemScript));
676  // Now check if the redeemScript is actually a P2WSH script
677  CTxDestination witness_destination;
678  if (redeemScript.IsPayToWitnessScriptHash()) {
679  bool extracted = ExtractDestination(redeemScript, witness_destination);
680  CHECK_NONFATAL(extracted);
681  // Also return the witness script
682  const WitnessV0ScriptHash& whash = std::get<WitnessV0ScriptHash>(witness_destination);
683  CScriptID id{RIPEMD160(whash)};
684  CScript witnessScript;
685  if (provider->GetCScript(id, witnessScript)) {
686  entry.pushKV("witnessScript", HexStr(witnessScript));
687  }
688  }
689  }
690  } else if (scriptPubKey.IsPayToWitnessScriptHash()) {
691  const WitnessV0ScriptHash& whash = std::get<WitnessV0ScriptHash>(address);
692  CScriptID id{RIPEMD160(whash)};
693  CScript witnessScript;
694  if (provider->GetCScript(id, witnessScript)) {
695  entry.pushKV("witnessScript", HexStr(witnessScript));
696  }
697  }
698  }
699  }
700 
701  entry.pushKV("scriptPubKey", HexStr(scriptPubKey));
702  entry.pushKV("amount", ValueFromAmount(out.txout.nValue));
703  entry.pushKV("confirmations", out.depth);
704  if (!out.depth) {
705  size_t ancestor_count, descendant_count, ancestor_size;
706  CAmount ancestor_fees;
707  pwallet->chain().getTransactionAncestry(out.outpoint.hash, ancestor_count, descendant_count, &ancestor_size, &ancestor_fees);
708  if (ancestor_count) {
709  entry.pushKV("ancestorcount", uint64_t(ancestor_count));
710  entry.pushKV("ancestorsize", uint64_t(ancestor_size));
711  entry.pushKV("ancestorfees", uint64_t(ancestor_fees));
712  }
713  }
714  entry.pushKV("spendable", out.spendable);
715  entry.pushKV("solvable", out.solvable);
716  if (out.solvable) {
717  std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);
718  if (provider) {
719  auto descriptor = InferDescriptor(scriptPubKey, *provider);
720  entry.pushKV("desc", descriptor->ToString());
721  }
722  }
723  PushParentDescriptors(*pwallet, scriptPubKey, entry);
724  if (avoid_reuse) entry.pushKV("reused", reused);
725  entry.pushKV("safe", out.safe);
726  results.push_back(entry);
727  }
728 
729  return results;
730 },
731  };
732 }
733 } // namespace wallet
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
int ret
static CAmount AmountFromValue(const UniValue &value)
Definition: bitcoin-tx.cpp:550
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:46
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:36
uint32_t n
Definition: transaction.h:39
uint256 hash
Definition: transaction.h:38
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:411
bool IsPayToScriptHash() const
Definition: script.cpp:201
bool IsPayToWitnessScriptHash() const
Definition: script.cpp:210
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:27
An output of a transaction.
Definition: transaction.h:158
CScript scriptPubKey
Definition: transaction.h:161
CAmount nValue
Definition: transaction.h:160
void push_back(UniValue val)
Definition: univalue.cpp:104
const std::string & get_str() const
@ VNULL
Definition: univalue.h:20
@ VOBJ
Definition: univalue.h:20
@ VSTR
Definition: univalue.h:20
@ VARR
Definition: univalue.h:20
@ VNUM
Definition: univalue.h:20
@ VBOOL
Definition: univalue.h:20
bool isNull() const
Definition: univalue.h:75
const UniValue & get_obj() const
size_t size() const
Definition: univalue.h:67
Int getInt() const
Definition: univalue.h:138
const UniValue & get_array() const
bool exists(const std::string &key) const
Definition: univalue.h:73
void pushKV(std::string key, UniValue val)
Definition: univalue.cpp:126
bool get_bool() const
iterator insert(iterator pos, const T &value)
Definition: prevector.h:349
256-bit opaque blob.
Definition: uint256.h:119
Coin Control Features.
Definition: coincontrol.h:30
bool m_avoid_address_reuse
Forbids inclusion of dirty (previously used) addresses.
Definition: coincontrol.h:54
int m_min_depth
Minimum chain depth value for coin availability.
Definition: coincontrol.h:58
int m_max_depth
Maximum chain depth value for coin availability.
Definition: coincontrol.h:60
bool m_include_unsafe_inputs
If false, only safe inputs will be used.
Definition: coincontrol.h:37
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:237
A transaction with a bunch of additional info that only the owner cares about.
Definition: transaction.h:138
CTransactionRef tx
Definition: transaction.h:219
bool IsCoinBase() const
Definition: transaction.h:301
UniValue ValueFromAmount(const CAmount amount)
Definition: core_write.cpp:26
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible.
const std::string CURRENCY_ATOM
Definition: feerate.h:18
const std::string CURRENCY_UNIT
Definition: feerate.h:17
uint160 RIPEMD160(Span< const unsigned char > data)
Compute the 160-bit RIPEMD-160 hash of an array.
Definition: hash.h:286
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
Definition: key_io.cpp:281
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:276
std::string FormatMoney(const CAmount n)
Money parsing/formatting utilities.
Definition: moneystr.cpp:16
Definition: node.h:39
Balance GetBalance(const CWallet &wallet, const int min_depth, bool avoid_reuse)
Definition: receive.cpp:293
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: util.cpp:71
RPCHelpMan listlockunspent()
Definition: coins.cpp:376
RPCHelpMan getreceivedbyaddress()
Definition: coins.cpp:80
RPCHelpMan getbalance()
Definition: coins.cpp:162
void PushParentDescriptors(const CWallet &wallet, const CScript &script_pubkey, UniValue &entry)
Fetch parent descriptors of this scriptPubKey.
Definition: util.cpp:144
std::string LabelFromValue(const UniValue &value)
Definition: util.cpp:133
RPCHelpMan lockunspent()
Definition: coins.cpp:240
CoinsResult AvailableCoinsListUnspent(const CWallet &wallet, const CCoinControl *coinControl, CoinFilterParams params)
Wrapper function for AvailableCoins which skips the feerate and CoinFilterParams::only_spendable para...
Definition: spend.cpp:353
bool ParseIncludeWatchonly(const UniValue &include_watchonly, const CWallet &wallet)
Used by RPC commands that have an include_watchonly parameter.
Definition: util.cpp:50
RPCHelpMan getreceivedbylabel()
Definition: coins.cpp:121
RPCHelpMan getbalances()
Definition: coins.cpp:429
static CAmount GetReceived(const CWallet &wallet, const UniValue &params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
Definition: coins.cpp:20
bool GetAvoidReuseFlag(const CWallet &wallet, const UniValue &param)
Definition: util.cpp:35
RPCHelpMan listunspent()
Definition: coins.cpp:496
@ WALLET_FLAG_AVOID_REUSE
Definition: walletutil.h:42
RPCHelpMan getunconfirmedbalance()
Definition: coins.cpp:217
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:56
@ RPC_METHOD_DEPRECATED
RPC method is deprecated.
Definition: protocol.h:50
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
Definition: protocol.h:43
@ RPC_WALLET_ERROR
Wallet errors.
Definition: protocol.h:71
@ RPC_INVALID_ADDRESS_OR_KEY
Invalid address or key.
Definition: protocol.h:41
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:139
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:157
uint256 ParseHashO(const UniValue &o, std::string strKey)
Definition: util.cpp:82
const std::string EXAMPLE_ADDRESS[2]
Example bech32 addresses for the RPCExamples help documentation.
Definition: util.cpp:22
void RPCTypeCheckObj(const UniValue &o, const std::map< std::string, UniValueType > &typesExpected, bool fAllowNull, bool fStrict)
Definition: util.cpp:34
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:237
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:356
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Definition: standard.cpp:334
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:149
@ STR_HEX
Special type that is a STR with only hex chars.
@ AMOUNT
Special type representing a floating point amount (can be either NUM or STR)
std::string DefaultHint
Hint for default value.
Definition: util.h:162
@ OMITTED
Optional argument for which the default value is omitted from help text for one of two reasons:
@ NO
Required arg.
std::string oneline_description
Should be empty unless it is supposed to override the auto-generated summary line.
Definition: util.h:130
@ STR_HEX
Special string with only hex chars.
@ STR_AMOUNT
Special string to represent a floating point amount.
Wrapper for UniValue::VType, which includes typeAny: Used to denote don't care type.
Definition: util.h:58
CAmount m_mine_untrusted_pending
Untrusted, but in mempool (pending)
Definition: receive.h:53
A UTXO under consideration for use in funding a new transaction.
Definition: coinselection.h:25
uint64_t max_count
Definition: spend.h:74
bool include_immature_coinbase
Definition: spend.h:78
CAmount min_sum_amount
Definition: spend.h:72
std::vector< COutput > All() const
Concatenate and return all COutputs as one vector.
Definition: spend.cpp:94
#define LOCK(cs)
Definition: sync.h:258
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:49
const UniValue & find_value(const UniValue &obj, const std::string &name)
Definition: univalue.cpp:233
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.