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