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