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