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>(0)};
198  if (dummy_value && *dummy_value != "*") {
199  throw JSONRPCError(RPC_METHOD_DEPRECATED, "dummy first argument must be excluded or set to \"*\".");
200  }
201 
202  int min_depth = 0;
203  if (!request.params[1].isNull()) {
204  min_depth = request.params[1].getInt<int>();
205  }
206 
207  bool include_watchonly = ParseIncludeWatchonly(request.params[2], *pwallet);
208 
209  bool avoid_reuse = GetAvoidReuseFlag(*pwallet, request.params[3]);
210 
211  const auto bal = GetBalance(*pwallet, min_depth, avoid_reuse);
212 
213  return ValueFromAmount(bal.m_mine_trusted + (include_watchonly ? bal.m_watchonly_trusted : 0));
214 },
215  };
216 }
217 
219 {
220  return RPCHelpMan{"getunconfirmedbalance",
221  "DEPRECATED\nIdentical to getbalances().mine.untrusted_pending\n",
222  {},
223  RPCResult{RPCResult::Type::NUM, "", "The balance"},
224  RPCExamples{""},
225  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
226 {
227  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
228  if (!pwallet) return UniValue::VNULL;
229 
230  // Make sure the results are valid at least up to the most recent block
231  // the user could have gotten from another RPC command prior to now
232  pwallet->BlockUntilSyncedToCurrentChain();
233 
234  LOCK(pwallet->cs_wallet);
235 
237 },
238  };
239 }
240 
242 {
243  return RPCHelpMan{"lockunspent",
244  "\nUpdates list of temporarily unspendable outputs.\n"
245  "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
246  "If no transaction outputs are specified when unlocking then all current locked transaction outputs are unlocked.\n"
247  "A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n"
248  "Manually selected coins are automatically unlocked.\n"
249  "Locks are stored in memory only, unless persistent=true, in which case they will be written to the\n"
250  "wallet database and loaded on node start. Unwritten (persistent=false) locks are always cleared\n"
251  "(by virtue of process exit) when a node stops or fails. Unlocking will clear both persistent and not.\n"
252  "Also see the listunspent call\n",
253  {
254  {"unlock", RPCArg::Type::BOOL, RPCArg::Optional::NO, "Whether to unlock (true) or lock (false) the specified transactions"},
255  {"transactions", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "The transaction outputs and within each, the txid (string) vout (numeric).",
256  {
258  {
259  {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
260  {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
261  },
262  },
263  },
264  },
265  {"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."},
266  },
267  RPCResult{
268  RPCResult::Type::BOOL, "", "Whether the command was successful or not"
269  },
270  RPCExamples{
271  "\nList the unspent transactions\n"
272  + HelpExampleCli("listunspent", "") +
273  "\nLock an unspent transaction\n"
274  + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
275  "\nList the locked transactions\n"
276  + HelpExampleCli("listlockunspent", "") +
277  "\nUnlock the transaction again\n"
278  + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
279  "\nLock the transaction persistently in the wallet database\n"
280  + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\" true") +
281  "\nAs a JSON-RPC call\n"
282  + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
283  },
284  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
285 {
286  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
287  if (!pwallet) return UniValue::VNULL;
288 
289  // Make sure the results are valid at least up to the most recent block
290  // the user could have gotten from another RPC command prior to now
291  pwallet->BlockUntilSyncedToCurrentChain();
292 
293  LOCK(pwallet->cs_wallet);
294 
295  bool fUnlock = request.params[0].get_bool();
296 
297  const bool persistent{request.params[2].isNull() ? false : request.params[2].get_bool()};
298 
299  if (request.params[1].isNull()) {
300  if (fUnlock) {
301  if (!pwallet->UnlockAllCoins())
302  throw JSONRPCError(RPC_WALLET_ERROR, "Unlocking coins failed");
303  }
304  return true;
305  }
306 
307  const UniValue& output_params = request.params[1].get_array();
308 
309  // Create and validate the COutPoints first.
310 
311  std::vector<COutPoint> outputs;
312  outputs.reserve(output_params.size());
313 
314  for (unsigned int idx = 0; idx < output_params.size(); idx++) {
315  const UniValue& o = output_params[idx].get_obj();
316 
317  RPCTypeCheckObj(o,
318  {
319  {"txid", UniValueType(UniValue::VSTR)},
320  {"vout", UniValueType(UniValue::VNUM)},
321  });
322 
323  const Txid txid = Txid::FromUint256(ParseHashO(o, "txid"));
324  const int nOutput = o.find_value("vout").getInt<int>();
325  if (nOutput < 0) {
326  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout cannot be negative");
327  }
328 
329  const COutPoint outpt(txid, nOutput);
330 
331  const auto it = pwallet->mapWallet.find(outpt.hash);
332  if (it == pwallet->mapWallet.end()) {
333  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, unknown transaction");
334  }
335 
336  const CWalletTx& trans = it->second;
337 
338  if (outpt.n >= trans.tx->vout.size()) {
339  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout index out of bounds");
340  }
341 
342  if (pwallet->IsSpent(outpt)) {
343  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected unspent output");
344  }
345 
346  const bool is_locked = pwallet->IsLockedCoin(outpt);
347 
348  if (fUnlock && !is_locked) {
349  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected locked output");
350  }
351 
352  if (!fUnlock && is_locked && !persistent) {
353  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, output already locked");
354  }
355 
356  outputs.push_back(outpt);
357  }
358 
359  std::unique_ptr<WalletBatch> batch = nullptr;
360  // Unlock is always persistent
361  if (fUnlock || persistent) batch = std::make_unique<WalletBatch>(pwallet->GetDatabase());
362 
363  // Atomically set (un)locked status for the outputs.
364  for (const COutPoint& outpt : outputs) {
365  if (fUnlock) {
366  if (!pwallet->UnlockCoin(outpt, batch.get())) throw JSONRPCError(RPC_WALLET_ERROR, "Unlocking coin failed");
367  } else {
368  if (!pwallet->LockCoin(outpt, batch.get())) throw JSONRPCError(RPC_WALLET_ERROR, "Locking coin failed");
369  }
370  }
371 
372  return true;
373 },
374  };
375 }
376 
378 {
379  return RPCHelpMan{"listlockunspent",
380  "\nReturns list of temporarily unspendable outputs.\n"
381  "See the lockunspent call to lock and unlock transactions for spending.\n",
382  {},
383  RPCResult{
384  RPCResult::Type::ARR, "", "",
385  {
386  {RPCResult::Type::OBJ, "", "",
387  {
388  {RPCResult::Type::STR_HEX, "txid", "The transaction id locked"},
389  {RPCResult::Type::NUM, "vout", "The vout value"},
390  }},
391  }
392  },
393  RPCExamples{
394  "\nList the unspent transactions\n"
395  + HelpExampleCli("listunspent", "") +
396  "\nLock an unspent transaction\n"
397  + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
398  "\nList the locked transactions\n"
399  + HelpExampleCli("listlockunspent", "") +
400  "\nUnlock the transaction again\n"
401  + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
402  "\nAs a JSON-RPC call\n"
403  + HelpExampleRpc("listlockunspent", "")
404  },
405  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
406 {
407  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
408  if (!pwallet) return UniValue::VNULL;
409 
410  LOCK(pwallet->cs_wallet);
411 
412  std::vector<COutPoint> vOutpts;
413  pwallet->ListLockedCoins(vOutpts);
414 
416 
417  for (const COutPoint& outpt : vOutpts) {
419 
420  o.pushKV("txid", outpt.hash.GetHex());
421  o.pushKV("vout", (int)outpt.n);
422  ret.push_back(o);
423  }
424 
425  return ret;
426 },
427  };
428 }
429 
431 {
432  return RPCHelpMan{
433  "getbalances",
434  "Returns an object with all balances in " + CURRENCY_UNIT + ".\n",
435  {},
436  RPCResult{
437  RPCResult::Type::OBJ, "", "",
438  {
439  {RPCResult::Type::OBJ, "mine", "balances from outputs that the wallet can sign",
440  {
441  {RPCResult::Type::STR_AMOUNT, "trusted", "trusted balance (outputs created by the wallet or confirmed outputs)"},
442  {RPCResult::Type::STR_AMOUNT, "untrusted_pending", "untrusted pending balance (outputs created by others that are in the mempool)"},
443  {RPCResult::Type::STR_AMOUNT, "immature", "balance from immature coinbase outputs"},
444  {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)"},
445  }},
446  {RPCResult::Type::OBJ, "watchonly", /*optional=*/true, "watchonly balances (not present if wallet does not watch anything)",
447  {
448  {RPCResult::Type::STR_AMOUNT, "trusted", "trusted balance (outputs created by the wallet or confirmed outputs)"},
449  {RPCResult::Type::STR_AMOUNT, "untrusted_pending", "untrusted pending balance (outputs created by others that are in the mempool)"},
450  {RPCResult::Type::STR_AMOUNT, "immature", "balance from immature coinbase outputs"},
451  }},
453  }
454  },
455  RPCExamples{
456  HelpExampleCli("getbalances", "") +
457  HelpExampleRpc("getbalances", "")},
458  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
459 {
460  const std::shared_ptr<const CWallet> rpc_wallet = GetWalletForJSONRPCRequest(request);
461  if (!rpc_wallet) return UniValue::VNULL;
462  const CWallet& wallet = *rpc_wallet;
463 
464  // Make sure the results are valid at least up to the most recent block
465  // the user could have gotten from another RPC command prior to now
466  wallet.BlockUntilSyncedToCurrentChain();
467 
468  LOCK(wallet.cs_wallet);
469 
470  const auto bal = GetBalance(wallet);
471  UniValue balances{UniValue::VOBJ};
472  {
473  UniValue balances_mine{UniValue::VOBJ};
474  balances_mine.pushKV("trusted", ValueFromAmount(bal.m_mine_trusted));
475  balances_mine.pushKV("untrusted_pending", ValueFromAmount(bal.m_mine_untrusted_pending));
476  balances_mine.pushKV("immature", ValueFromAmount(bal.m_mine_immature));
477  if (wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE)) {
478  // If the AVOID_REUSE flag is set, bal has been set to just the un-reused address balance. Get
479  // the total balance, and then subtract bal to get the reused address balance.
480  const auto full_bal = GetBalance(wallet, 0, false);
481  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));
482  }
483  balances.pushKV("mine", balances_mine);
484  }
485  auto spk_man = wallet.GetLegacyScriptPubKeyMan();
486  if (spk_man && spk_man->HaveWatchOnly()) {
487  UniValue balances_watchonly{UniValue::VOBJ};
488  balances_watchonly.pushKV("trusted", ValueFromAmount(bal.m_watchonly_trusted));
489  balances_watchonly.pushKV("untrusted_pending", ValueFromAmount(bal.m_watchonly_untrusted_pending));
490  balances_watchonly.pushKV("immature", ValueFromAmount(bal.m_watchonly_immature));
491  balances.pushKV("watchonly", balances_watchonly);
492  }
493 
494  AppendLastProcessedBlock(balances, wallet);
495  return balances;
496 },
497  };
498 }
499 
501 {
502  return RPCHelpMan{
503  "listunspent",
504  "\nReturns array of unspent transaction outputs\n"
505  "with between minconf and maxconf (inclusive) confirmations.\n"
506  "Optionally filter to only include txouts paid to specified addresses.\n",
507  {
508  {"minconf", RPCArg::Type::NUM, RPCArg::Default{1}, "The minimum confirmations to filter"},
509  {"maxconf", RPCArg::Type::NUM, RPCArg::Default{9999999}, "The maximum confirmations to filter"},
510  {"addresses", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "The bitcoin addresses to filter",
511  {
512  {"address", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "bitcoin address"},
513  },
514  },
515  {"include_unsafe", RPCArg::Type::BOOL, RPCArg::Default{true}, "Include outputs that are not safe to spend\n"
516  "See description of \"safe\" attribute below."},
518  {
519  {"minimumAmount", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(0)}, "Minimum value of each UTXO in " + CURRENCY_UNIT + ""},
520  {"maximumAmount", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"unlimited"}, "Maximum value of each UTXO in " + CURRENCY_UNIT + ""},
521  {"maximumCount", RPCArg::Type::NUM, RPCArg::DefaultHint{"unlimited"}, "Maximum number of UTXOs"},
522  {"minimumSumAmount", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"unlimited"}, "Minimum sum value of all UTXOs in " + CURRENCY_UNIT + ""},
523  {"include_immature_coinbase", RPCArg::Type::BOOL, RPCArg::Default{false}, "Include immature coinbase UTXOs"}
524  },
525  RPCArgOptions{.oneline_description="query_options"}},
526  },
527  RPCResult{
528  RPCResult::Type::ARR, "", "",
529  {
530  {RPCResult::Type::OBJ, "", "",
531  {
532  {RPCResult::Type::STR_HEX, "txid", "the transaction id"},
533  {RPCResult::Type::NUM, "vout", "the vout value"},
534  {RPCResult::Type::STR, "address", /*optional=*/true, "the bitcoin address"},
535  {RPCResult::Type::STR, "label", /*optional=*/true, "The associated label, or \"\" for the default label"},
536  {RPCResult::Type::STR, "scriptPubKey", "the script key"},
537  {RPCResult::Type::STR_AMOUNT, "amount", "the transaction output amount in " + CURRENCY_UNIT},
538  {RPCResult::Type::NUM, "confirmations", "The number of confirmations"},
539  {RPCResult::Type::NUM, "ancestorcount", /*optional=*/true, "The number of in-mempool ancestor transactions, including this one (if transaction is in the mempool)"},
540  {RPCResult::Type::NUM, "ancestorsize", /*optional=*/true, "The virtual transaction size of in-mempool ancestors, including this one (if transaction is in the mempool)"},
541  {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)"},
542  {RPCResult::Type::STR_HEX, "redeemScript", /*optional=*/true, "The redeemScript if scriptPubKey is P2SH"},
543  {RPCResult::Type::STR, "witnessScript", /*optional=*/true, "witnessScript if the scriptPubKey is P2WSH or P2SH-P2WSH"},
544  {RPCResult::Type::BOOL, "spendable", "Whether we have the private keys to spend this output"},
545  {RPCResult::Type::BOOL, "solvable", "Whether we know how to spend this output, ignoring the lack of keys"},
546  {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)"},
547  {RPCResult::Type::STR, "desc", /*optional=*/true, "(only when solvable) A descriptor for spending this output"},
548  {RPCResult::Type::ARR, "parent_descs", /*optional=*/false, "List of parent descriptors for the scriptPubKey of this coin.", {
549  {RPCResult::Type::STR, "desc", "The descriptor string."},
550  }},
551  {RPCResult::Type::BOOL, "safe", "Whether this output is considered safe to spend. Unconfirmed transactions\n"
552  "from outside keys and unconfirmed replacement transactions are considered unsafe\n"
553  "and are not eligible for spending by fundrawtransaction and sendtoaddress."},
554  }},
555  }
556  },
557  RPCExamples{
558  HelpExampleCli("listunspent", "")
559  + HelpExampleCli("listunspent", "6 9999999 \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"")
560  + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"")
561  + HelpExampleCli("listunspent", "6 9999999 '[]' true '{ \"minimumAmount\": 0.005 }'")
562  + HelpExampleRpc("listunspent", "6, 9999999, [] , true, { \"minimumAmount\": 0.005 } ")
563  },
564  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
565 {
566  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
567  if (!pwallet) return UniValue::VNULL;
568 
569  int nMinDepth = 1;
570  if (!request.params[0].isNull()) {
571  nMinDepth = request.params[0].getInt<int>();
572  }
573 
574  int nMaxDepth = 9999999;
575  if (!request.params[1].isNull()) {
576  nMaxDepth = request.params[1].getInt<int>();
577  }
578 
579  std::set<CTxDestination> destinations;
580  if (!request.params[2].isNull()) {
581  UniValue inputs = request.params[2].get_array();
582  for (unsigned int idx = 0; idx < inputs.size(); idx++) {
583  const UniValue& input = inputs[idx];
584  CTxDestination dest = DecodeDestination(input.get_str());
585  if (!IsValidDestination(dest)) {
586  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + input.get_str());
587  }
588  if (!destinations.insert(dest).second) {
589  throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + input.get_str());
590  }
591  }
592  }
593 
594  bool include_unsafe = true;
595  if (!request.params[3].isNull()) {
596  include_unsafe = request.params[3].get_bool();
597  }
598 
599  CoinFilterParams filter_coins;
600  filter_coins.min_amount = 0;
601 
602  if (!request.params[4].isNull()) {
603  const UniValue& options = request.params[4].get_obj();
604 
605  RPCTypeCheckObj(options,
606  {
607  {"minimumAmount", UniValueType()},
608  {"maximumAmount", UniValueType()},
609  {"minimumSumAmount", UniValueType()},
610  {"maximumCount", UniValueType(UniValue::VNUM)},
611  {"include_immature_coinbase", UniValueType(UniValue::VBOOL)}
612  },
613  true, true);
614 
615  if (options.exists("minimumAmount"))
616  filter_coins.min_amount = AmountFromValue(options["minimumAmount"]);
617 
618  if (options.exists("maximumAmount"))
619  filter_coins.max_amount = AmountFromValue(options["maximumAmount"]);
620 
621  if (options.exists("minimumSumAmount"))
622  filter_coins.min_sum_amount = AmountFromValue(options["minimumSumAmount"]);
623 
624  if (options.exists("maximumCount"))
625  filter_coins.max_count = options["maximumCount"].getInt<int64_t>();
626 
627  if (options.exists("include_immature_coinbase")) {
628  filter_coins.include_immature_coinbase = options["include_immature_coinbase"].get_bool();
629  }
630  }
631 
632  // Make sure the results are valid at least up to the most recent block
633  // the user could have gotten from another RPC command prior to now
634  pwallet->BlockUntilSyncedToCurrentChain();
635 
636  UniValue results(UniValue::VARR);
637  std::vector<COutput> vecOutputs;
638  {
639  CCoinControl cctl;
640  cctl.m_avoid_address_reuse = false;
641  cctl.m_min_depth = nMinDepth;
642  cctl.m_max_depth = nMaxDepth;
643  cctl.m_include_unsafe_inputs = include_unsafe;
644  LOCK(pwallet->cs_wallet);
645  vecOutputs = AvailableCoinsListUnspent(*pwallet, &cctl, filter_coins).All();
646  }
647 
648  LOCK(pwallet->cs_wallet);
649 
650  const bool avoid_reuse = pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE);
651 
652  for (const COutput& out : vecOutputs) {
653  CTxDestination address;
654  const CScript& scriptPubKey = out.txout.scriptPubKey;
655  bool fValidAddress = ExtractDestination(scriptPubKey, address);
656  bool reused = avoid_reuse && pwallet->IsSpentKey(scriptPubKey);
657 
658  if (destinations.size() && (!fValidAddress || !destinations.count(address)))
659  continue;
660 
661  UniValue entry(UniValue::VOBJ);
662  entry.pushKV("txid", out.outpoint.hash.GetHex());
663  entry.pushKV("vout", (int)out.outpoint.n);
664 
665  if (fValidAddress) {
666  entry.pushKV("address", EncodeDestination(address));
667 
668  const auto* address_book_entry = pwallet->FindAddressBookEntry(address);
669  if (address_book_entry) {
670  entry.pushKV("label", address_book_entry->GetLabel());
671  }
672 
673  std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);
674  if (provider) {
675  if (scriptPubKey.IsPayToScriptHash()) {
676  const CScriptID hash = ToScriptID(std::get<ScriptHash>(address));
677  CScript redeemScript;
678  if (provider->GetCScript(hash, redeemScript)) {
679  entry.pushKV("redeemScript", HexStr(redeemScript));
680  // Now check if the redeemScript is actually a P2WSH script
681  CTxDestination witness_destination;
682  if (redeemScript.IsPayToWitnessScriptHash()) {
683  bool extracted = ExtractDestination(redeemScript, witness_destination);
684  CHECK_NONFATAL(extracted);
685  // Also return the witness script
686  const WitnessV0ScriptHash& whash = std::get<WitnessV0ScriptHash>(witness_destination);
687  CScriptID id{RIPEMD160(whash)};
688  CScript witnessScript;
689  if (provider->GetCScript(id, witnessScript)) {
690  entry.pushKV("witnessScript", HexStr(witnessScript));
691  }
692  }
693  }
694  } else if (scriptPubKey.IsPayToWitnessScriptHash()) {
695  const WitnessV0ScriptHash& whash = std::get<WitnessV0ScriptHash>(address);
696  CScriptID id{RIPEMD160(whash)};
697  CScript witnessScript;
698  if (provider->GetCScript(id, witnessScript)) {
699  entry.pushKV("witnessScript", HexStr(witnessScript));
700  }
701  }
702  }
703  }
704 
705  entry.pushKV("scriptPubKey", HexStr(scriptPubKey));
706  entry.pushKV("amount", ValueFromAmount(out.txout.nValue));
707  entry.pushKV("confirmations", out.depth);
708  if (!out.depth) {
709  size_t ancestor_count, descendant_count, ancestor_size;
710  CAmount ancestor_fees;
711  pwallet->chain().getTransactionAncestry(out.outpoint.hash, ancestor_count, descendant_count, &ancestor_size, &ancestor_fees);
712  if (ancestor_count) {
713  entry.pushKV("ancestorcount", uint64_t(ancestor_count));
714  entry.pushKV("ancestorsize", uint64_t(ancestor_size));
715  entry.pushKV("ancestorfees", uint64_t(ancestor_fees));
716  }
717  }
718  entry.pushKV("spendable", out.spendable);
719  entry.pushKV("solvable", out.solvable);
720  if (out.solvable) {
721  std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);
722  if (provider) {
723  auto descriptor = InferDescriptor(scriptPubKey, *provider);
724  entry.pushKV("desc", descriptor->ToString());
725  }
726  }
727  PushParentDescriptors(*pwallet, scriptPubKey, entry);
728  if (avoid_reuse) entry.pushKV("reused", reused);
729  entry.pushKV("safe", out.safe);
730  results.push_back(entry);
731  }
732 
733  return results;
734 },
735  };
736 }
737 } // 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:377
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:241
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:430
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:500
@ WALLET_FLAG_AVOID_REUSE
Definition: walletutil.h:42
RPCHelpMan getunconfirmedbalance()
Definition: coins.cpp:218
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:155
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:173
const std::string EXAMPLE_ADDRESS[2]
Example bech32 addresses for the RPCExamples help documentation.
Definition: util.cpp:31
uint256 ParseHashO(const UniValue &o, std::string_view strKey)
Definition: util.cpp:98
void RPCTypeCheckObj(const UniValue &o, const std::map< std::string, UniValueType > &typesExpected, bool fAllowNull, bool fStrict)
Definition: util.cpp:43
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.