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