Bitcoin Core 30.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
20namespace wallet {
21static 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.count(txout.scriptPubKey) > 0) {
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 },
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 },
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 },
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 },
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
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 },
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", (int)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 },
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 }
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 },
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];
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.count(address)))
616 continue;
617
619 entry.pushKV("txid", out.outpoint.hash.GetHex());
620 entry.pushKV("vout", (int)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, descendant_count, ancestor_size;
667 CAmount ancestor_fees;
668 pwallet->chain().getTransactionAncestry(out.outpoint.hash, ancestor_count, descendant_count, &ancestor_size, &ancestor_fees);
669 if (ancestor_count) {
670 entry.pushKV("ancestorcount", uint64_t(ancestor_count));
671 entry.pushKV("ancestorsize", uint64_t(ancestor_size));
672 entry.pushKV("ancestorfees", uint64_t(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
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, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
Definition: addresstype.h:143
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:554
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:111
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:413
bool IsPayToScriptHash() const
Definition: script.cpp:224
bool IsPayToWitnessScriptHash() const
Definition: script.cpp:233
A reference to a CScript: the Hash160 of its serialization.
Definition: script.h:602
An output of a transaction.
Definition: transaction.h:150
CScript scriptPubKey
Definition: transaction.h:153
CAmount nValue
Definition: transaction.h:152
auto Arg(std::string_view key) const
Helper to get a required or default-valued request argument.
Definition: util.h:444
auto MaybeArg(std::string_view key) const
Helper to get an optional request argument.
Definition: util.h:476
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:140
const UniValue & get_array() const
bool exists(const std::string &key) const
Definition: univalue.h:79
void reserve(size_t new_cap)
Definition: univalue.cpp:243
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:315
static transaction_identifier FromUint256(const uint256 &id)
Coin Control Features.
Definition: coincontrol.h:83
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:90
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:311
A transaction with a bunch of additional info that only the owner cares about.
Definition: transaction.h:195
CTransactionRef tx
Definition: transaction.h:269
UniValue ValueFromAmount(const CAmount amount)
Definition: core_write.cpp:26
const std::string CURRENCY_ATOM
Definition: feerate.h:19
const std::string CURRENCY_UNIT
Definition: feerate.h:18
uint160 RIPEMD160(std::span< const unsigned char > data)
Compute the 160-bit RIPEMD-160 hash of an array.
Definition: hash.h:222
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:31
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
Definition: key_io.cpp:299
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:294
std::string FormatMoney(const CAmount n)
Money parsing/formatting utilities.
Definition: moneystr.cpp:19
Balance GetBalance(const CWallet &wallet, const int min_depth, bool avoid_reuse)
Definition: receive.cpp:245
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: util.cpp:64
RPCHelpMan listlockunspent()
Definition: coins.cpp:347
static const RPCResult RESULT_LAST_PROCESSED_BLOCK
Definition: util.h:30
RPCHelpMan getreceivedbyaddress()
Definition: coins.cpp:80
RPCHelpMan getbalance()
Definition: coins.cpp:164
void PushParentDescriptors(const CWallet &wallet, const CScript &script_pubkey, UniValue &entry)
Fetch parent descriptors of this scriptPubKey.
Definition: util.cpp:115
std::string LabelFromValue(const UniValue &value)
Definition: util.cpp:104
RPCHelpMan lockunspent()
Definition: coins.cpp:214
void AppendLastProcessedBlock(UniValue &entry, const CWallet &wallet)
Definition: util.cpp:155
RPCHelpMan getreceivedbylabel()
Definition: coins.cpp:122
RPCHelpMan getbalances()
Definition: coins.cpp:401
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:22
RPCHelpMan listunspent()
Definition: coins.cpp:456
@ WALLET_FLAG_AVOID_REUSE
Definition: walletutil.h:21
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
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:70
@ RPC_METHOD_DEPRECATED
RPC method is deprecated.
Definition: protocol.h:51
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
Definition: protocol.h:44
@ RPC_WALLET_ERROR
Wallet errors.
Definition: protocol.h:71
@ RPC_INVALID_ADDRESS_OR_KEY
Invalid address or key.
Definition: protocol.h:42
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:186
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:204
const std::string EXAMPLE_ADDRESS[2]
Example bech32 addresses for the RPCExamples help documentation.
Definition: util.cpp:47
uint256 ParseHashO(const UniValue &o, std::string_view strKey)
Definition: util.cpp:129
void RPCTypeCheckObj(const UniValue &o, const std::map< std::string, UniValueType > &typesExpected, bool fAllowNull, bool fStrict)
Definition: util.cpp:59
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:220
@ 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:171
@ 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:83
A UTXO under consideration for use in funding a new transaction.
Definition: coinselection.h:28
uint64_t max_count
Definition: spend.h:79
bool check_version_trucness
Definition: spend.h:86
bool include_immature_coinbase
Definition: spend.h:81
CAmount min_sum_amount
Definition: spend.h:77
std::vector< COutput > All() const
Concatenate and return all COutputs as one vector.
Definition: spend.cpp:203
#define LOCK(cs)
Definition: sync.h:259
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:51
consteval auto _(util::TranslatedLiteral str)
Definition: translation.h:79