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