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