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 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 }},
444 }
445 },
447 HelpExampleCli("getbalances", "") +
448 HelpExampleRpc("getbalances", "")},
449 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
450{
451 const std::shared_ptr<const CWallet> rpc_wallet = GetWalletForJSONRPCRequest(request);
452 if (!rpc_wallet) return UniValue::VNULL;
453 const CWallet& wallet = *rpc_wallet;
454
455 // Make sure the results are valid at least up to the most recent block
456 // the user could have gotten from another RPC command prior to now
457 wallet.BlockUntilSyncedToCurrentChain();
458
459 LOCK(wallet.cs_wallet);
460
461 const auto bal = GetBalance(wallet);
462 UniValue balances{UniValue::VOBJ};
463 {
464 UniValue balances_mine{UniValue::VOBJ};
465 balances_mine.pushKV("trusted", ValueFromAmount(bal.m_mine_trusted));
466 balances_mine.pushKV("untrusted_pending", ValueFromAmount(bal.m_mine_untrusted_pending));
467 balances_mine.pushKV("immature", ValueFromAmount(bal.m_mine_immature));
468 if (wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE)) {
469 // If the AVOID_REUSE flag is set, bal has been set to just the un-reused address balance. Get
470 // the total balance, and then subtract bal to get the reused address balance.
471 const auto full_bal = GetBalance(wallet, 0, false);
472 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));
473 }
474 balances.pushKV("mine", std::move(balances_mine));
475 }
477 return balances;
478},
479 };
480}
481
483{
484 return RPCHelpMan{
485 "listunspent",
486 "\nReturns array of unspent transaction outputs\n"
487 "with between minconf and maxconf (inclusive) confirmations.\n"
488 "Optionally filter to only include txouts paid to specified addresses.\n",
489 {
490 {"minconf", RPCArg::Type::NUM, RPCArg::Default{1}, "The minimum confirmations to filter"},
491 {"maxconf", RPCArg::Type::NUM, RPCArg::Default{9999999}, "The maximum confirmations to filter"},
492 {"addresses", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "The bitcoin addresses to filter",
493 {
494 {"address", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "bitcoin address"},
495 },
496 },
497 {"include_unsafe", RPCArg::Type::BOOL, RPCArg::Default{true}, "Include outputs that are not safe to spend\n"
498 "See description of \"safe\" attribute below."},
500 {
501 {"minimumAmount", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(0)}, "Minimum value of each UTXO in " + CURRENCY_UNIT + ""},
502 {"maximumAmount", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"unlimited"}, "Maximum value of each UTXO in " + CURRENCY_UNIT + ""},
503 {"maximumCount", RPCArg::Type::NUM, RPCArg::DefaultHint{"unlimited"}, "Maximum number of UTXOs"},
504 {"minimumSumAmount", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"unlimited"}, "Minimum sum value of all UTXOs in " + CURRENCY_UNIT + ""},
505 {"include_immature_coinbase", RPCArg::Type::BOOL, RPCArg::Default{false}, "Include immature coinbase UTXOs"}
506 },
507 RPCArgOptions{.oneline_description="query_options"}},
508 },
509 RPCResult{
510 RPCResult::Type::ARR, "", "",
511 {
512 {RPCResult::Type::OBJ, "", "",
513 {
514 {RPCResult::Type::STR_HEX, "txid", "the transaction id"},
515 {RPCResult::Type::NUM, "vout", "the vout value"},
516 {RPCResult::Type::STR, "address", /*optional=*/true, "the bitcoin address"},
517 {RPCResult::Type::STR, "label", /*optional=*/true, "The associated label, or \"\" for the default label"},
518 {RPCResult::Type::STR, "scriptPubKey", "the output script"},
519 {RPCResult::Type::STR_AMOUNT, "amount", "the transaction output amount in " + CURRENCY_UNIT},
520 {RPCResult::Type::NUM, "confirmations", "The number of confirmations"},
521 {RPCResult::Type::NUM, "ancestorcount", /*optional=*/true, "The number of in-mempool ancestor transactions, including this one (if transaction is in the mempool)"},
522 {RPCResult::Type::NUM, "ancestorsize", /*optional=*/true, "The virtual transaction size of in-mempool ancestors, including this one (if transaction is in the mempool)"},
523 {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)"},
524 {RPCResult::Type::STR_HEX, "redeemScript", /*optional=*/true, "The redeem script if the output script is P2SH"},
525 {RPCResult::Type::STR, "witnessScript", /*optional=*/true, "witness script if the output script is P2WSH or P2SH-P2WSH"},
526 {RPCResult::Type::BOOL, "spendable", "Whether we have the private keys to spend this output"},
527 {RPCResult::Type::BOOL, "solvable", "Whether we know how to spend this output, ignoring the lack of keys"},
528 {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)"},
529 {RPCResult::Type::STR, "desc", /*optional=*/true, "(only when solvable) A descriptor for spending this output"},
530 {RPCResult::Type::ARR, "parent_descs", /*optional=*/false, "List of parent descriptors for the output script of this coin.", {
531 {RPCResult::Type::STR, "desc", "The descriptor string."},
532 }},
533 {RPCResult::Type::BOOL, "safe", "Whether this output is considered safe to spend. Unconfirmed transactions\n"
534 "from outside keys and unconfirmed replacement transactions are considered unsafe\n"
535 "and are not eligible for spending by fundrawtransaction and sendtoaddress."},
536 }},
537 }
538 },
540 HelpExampleCli("listunspent", "")
541 + HelpExampleCli("listunspent", "6 9999999 \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"")
542 + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"")
543 + HelpExampleCli("listunspent", "6 9999999 '[]' true '{ \"minimumAmount\": 0.005 }'")
544 + HelpExampleRpc("listunspent", "6, 9999999, [] , true, { \"minimumAmount\": 0.005 } ")
545 },
546 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
547{
548 const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
549 if (!pwallet) return UniValue::VNULL;
550
551 int nMinDepth = 1;
552 if (!request.params[0].isNull()) {
553 nMinDepth = request.params[0].getInt<int>();
554 }
555
556 int nMaxDepth = 9999999;
557 if (!request.params[1].isNull()) {
558 nMaxDepth = request.params[1].getInt<int>();
559 }
560
561 std::set<CTxDestination> destinations;
562 if (!request.params[2].isNull()) {
563 UniValue inputs = request.params[2].get_array();
564 for (unsigned int idx = 0; idx < inputs.size(); idx++) {
565 const UniValue& input = inputs[idx];
567 if (!IsValidDestination(dest)) {
568 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + input.get_str());
569 }
570 if (!destinations.insert(dest).second) {
571 throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + input.get_str());
572 }
573 }
574 }
575
576 bool include_unsafe = true;
577 if (!request.params[3].isNull()) {
578 include_unsafe = request.params[3].get_bool();
579 }
580
581 CoinFilterParams filter_coins;
582 filter_coins.min_amount = 0;
583
584 if (!request.params[4].isNull()) {
585 const UniValue& options = request.params[4].get_obj();
586
587 RPCTypeCheckObj(options,
588 {
589 {"minimumAmount", UniValueType()},
590 {"maximumAmount", UniValueType()},
591 {"minimumSumAmount", UniValueType()},
592 {"maximumCount", UniValueType(UniValue::VNUM)},
593 {"include_immature_coinbase", UniValueType(UniValue::VBOOL)}
594 },
595 true, true);
596
597 if (options.exists("minimumAmount"))
598 filter_coins.min_amount = AmountFromValue(options["minimumAmount"]);
599
600 if (options.exists("maximumAmount"))
601 filter_coins.max_amount = AmountFromValue(options["maximumAmount"]);
602
603 if (options.exists("minimumSumAmount"))
604 filter_coins.min_sum_amount = AmountFromValue(options["minimumSumAmount"]);
605
606 if (options.exists("maximumCount"))
607 filter_coins.max_count = options["maximumCount"].getInt<int64_t>();
608
609 if (options.exists("include_immature_coinbase")) {
610 filter_coins.include_immature_coinbase = options["include_immature_coinbase"].get_bool();
611 }
612 }
613
614 // Make sure the results are valid at least up to the most recent block
615 // the user could have gotten from another RPC command prior to now
616 pwallet->BlockUntilSyncedToCurrentChain();
617
618 UniValue results(UniValue::VARR);
619 std::vector<COutput> vecOutputs;
620 {
621 CCoinControl cctl;
622 cctl.m_avoid_address_reuse = false;
623 cctl.m_min_depth = nMinDepth;
624 cctl.m_max_depth = nMaxDepth;
625 cctl.m_include_unsafe_inputs = include_unsafe;
626 LOCK(pwallet->cs_wallet);
627 vecOutputs = AvailableCoinsListUnspent(*pwallet, &cctl, filter_coins).All();
628 }
629
630 LOCK(pwallet->cs_wallet);
631
632 const bool avoid_reuse = pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE);
633
634 for (const COutput& out : vecOutputs) {
635 CTxDestination address;
636 const CScript& scriptPubKey = out.txout.scriptPubKey;
637 bool fValidAddress = ExtractDestination(scriptPubKey, address);
638 bool reused = avoid_reuse && pwallet->IsSpentKey(scriptPubKey);
639
640 if (destinations.size() && (!fValidAddress || !destinations.count(address)))
641 continue;
642
644 entry.pushKV("txid", out.outpoint.hash.GetHex());
645 entry.pushKV("vout", (int)out.outpoint.n);
646
647 if (fValidAddress) {
648 entry.pushKV("address", EncodeDestination(address));
649
650 const auto* address_book_entry = pwallet->FindAddressBookEntry(address);
651 if (address_book_entry) {
652 entry.pushKV("label", address_book_entry->GetLabel());
653 }
654
655 std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);
656 if (provider) {
657 if (scriptPubKey.IsPayToScriptHash()) {
658 const CScriptID hash = ToScriptID(std::get<ScriptHash>(address));
659 CScript redeemScript;
660 if (provider->GetCScript(hash, redeemScript)) {
661 entry.pushKV("redeemScript", HexStr(redeemScript));
662 // Now check if the redeemScript is actually a P2WSH script
663 CTxDestination witness_destination;
664 if (redeemScript.IsPayToWitnessScriptHash()) {
665 bool extracted = ExtractDestination(redeemScript, witness_destination);
666 CHECK_NONFATAL(extracted);
667 // Also return the witness script
668 const WitnessV0ScriptHash& whash = std::get<WitnessV0ScriptHash>(witness_destination);
669 CScriptID id{RIPEMD160(whash)};
670 CScript witnessScript;
671 if (provider->GetCScript(id, witnessScript)) {
672 entry.pushKV("witnessScript", HexStr(witnessScript));
673 }
674 }
675 }
676 } else if (scriptPubKey.IsPayToWitnessScriptHash()) {
677 const WitnessV0ScriptHash& whash = std::get<WitnessV0ScriptHash>(address);
678 CScriptID id{RIPEMD160(whash)};
679 CScript witnessScript;
680 if (provider->GetCScript(id, witnessScript)) {
681 entry.pushKV("witnessScript", HexStr(witnessScript));
682 }
683 }
684 }
685 }
686
687 entry.pushKV("scriptPubKey", HexStr(scriptPubKey));
688 entry.pushKV("amount", ValueFromAmount(out.txout.nValue));
689 entry.pushKV("confirmations", out.depth);
690 if (!out.depth) {
691 size_t ancestor_count, descendant_count, ancestor_size;
692 CAmount ancestor_fees;
693 pwallet->chain().getTransactionAncestry(out.outpoint.hash, ancestor_count, descendant_count, &ancestor_size, &ancestor_fees);
694 if (ancestor_count) {
695 entry.pushKV("ancestorcount", uint64_t(ancestor_count));
696 entry.pushKV("ancestorsize", uint64_t(ancestor_size));
697 entry.pushKV("ancestorfees", uint64_t(ancestor_fees));
698 }
699 }
700 entry.pushKV("spendable", out.spendable);
701 entry.pushKV("solvable", out.solvable);
702 if (out.solvable) {
703 std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);
704 if (provider) {
705 auto descriptor = InferDescriptor(scriptPubKey, *provider);
706 entry.pushKV("desc", descriptor->ToString());
707 }
708 }
709 PushParentDescriptors(*pwallet, scriptPubKey, entry);
710 if (avoid_reuse) entry.pushKV("reused", reused);
711 entry.pushKV("safe", out.safe);
712 results.push_back(std::move(entry));
713 }
714
715 return results;
716},
717 };
718}
719} // 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:561
#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: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(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: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:108
std::string LabelFromValue(const UniValue &value)
Definition: util.cpp:97
RPCHelpMan lockunspent()
Definition: coins.cpp:238
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: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:482
@ 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: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: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