Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
501{RPCResult::Type::BOOL, "spendable", "(DEPRECATED) Always true"},502{RPCResult::Type::BOOL, "solvable", "Whether we know how to spend this output, ignoring the lack of keys"},503{RPCResult::Type::BOOL, "reused", /*optional=*/true, "(only present if avoid_reuse is set) Whether this output is reused/dirty (sent to an address that was previously spent from)"},504{RPCResult::Type::STR, "desc", /*optional=*/true, "(only when solvable) A descriptor for spending this output"},505{RPCResult::Type::ARR, "parent_descs", /*optional=*/false, "List of parent descriptors for the output script of this coin.", {506{RPCResult::Type::STR, "desc", "The descriptor string."},507}},508{RPCResult::Type::BOOL, "safe", "Whether this output is considered safe to spend. Unconfirmed transactions\n"509"from outside keys and unconfirmed replacement transactions are considered unsafe\n"510"and are not eligible for spending by fundrawtransaction and sendtoaddress."},511}},512}513},514RPCExamples{515HelpExampleCli("listunspent", "")516+ HelpExampleCli("listunspent", "6 9999999 \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"")517+ HelpExampleRpc("listunspent", strprintf(R"(6, 9999999, ["%s","%s"])", EXAMPLE_ADDRESS[0], EXAMPLE_ADDRESS[1]))518+ HelpExampleCli("listunspent", "6 9999999 '[]' true '{ \"minimumAmount\": 0.005 }'")519+ HelpExampleRpc("listunspent", "6, 9999999, [] , true, { \"minimumAmount\": 0.005 } ")520},521[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue522{523const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);524if (!pwallet) return UniValue::VNULL;526int nMinDepth = 1;527if (!request.params[0].isNull()) {528nMinDepth = request.params[0].getInt<int>();529}531int nMaxDepth = 9999999;532if (!request.params[1].isNull()) {533nMaxDepth = request.params[1].getInt<int>();534}536std::set<CTxDestination> destinations;537if (!request.params[2].isNull()) {538UniValue inputs = request.params[2].get_array();539for (unsigned int idx = 0; idx < inputs.size(); idx++) {540const UniValue& input = inputs[idx];541CTxDestination dest = DecodeDestination(input.get_str());542if (!IsValidDestination(dest)) {543throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + input.get_str());544}545if (!destinations.insert(dest).second) {546throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + input.get_str());547}548}549}551bool include_unsafe = true;552if (!request.params[3].isNull()) {553include_unsafe = request.params[3].get_bool();554}556CoinFilterParams filter_coins;557filter_coins.min_amount = 0;559if (!request.params[4].isNull()) {560const UniValue& options = request.params[4].get_obj();562RPCTypeCheckObj(options,563{564{"minimumAmount", UniValueType()},565{"maximumAmount", UniValueType()},566{"minimumSumAmount", UniValueType()},567{"maximumCount", UniValueType(UniValue::VNUM)},568{"include_immature_coinbase", UniValueType(UniValue::VBOOL)}569},570true, true);572if (options.exists("minimumAmount"))573filter_coins.min_amount = AmountFromValue(options["minimumAmount"]);575if (options.exists("maximumAmount"))576filter_coins.max_amount = AmountFromValue(options["maximumAmount"]);578if (options.exists("minimumSumAmount"))579filter_coins.min_sum_amount = AmountFromValue(options["minimumSumAmount"]);581if (options.exists("maximumCount"))582filter_coins.max_count = options["maximumCount"].getInt<int64_t>();584if (options.exists("include_immature_coinbase")) {585filter_coins.include_immature_coinbase = options["include_immature_coinbase"].get_bool();586}587}589// Make sure the results are valid at least up to the most recent block590// the user could have gotten from another RPC command prior to now591pwallet->BlockUntilSyncedToCurrentChain();593UniValue results(UniValue::VARR);594std::vector<COutput> vecOutputs;595{596CCoinControl cctl;597cctl.m_avoid_address_reuse = false;598cctl.m_min_depth = nMinDepth;599cctl.m_max_depth = nMaxDepth;600cctl.m_include_unsafe_inputs = include_unsafe;601filter_coins.check_version_trucness = false;602LOCK(pwallet->cs_wallet);603vecOutputs = AvailableCoins(*pwallet, &cctl, /*feerate=*/std::nullopt, filter_coins).All();604}606LOCK(pwallet->cs_wallet);608const bool avoid_reuse = pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE);610for (const COutput& out : vecOutputs) {611CTxDestination address;612const CScript& scriptPubKey = out.txout.scriptPubKey;613bool fValidAddress = ExtractDestination(scriptPubKey, address);614bool reused = avoid_reuse && pwallet->IsSpentKey(scriptPubKey);616if (destinations.size() && (!fValidAddress || !destinations.contains(address)))617continue;619UniValue entry(UniValue::VOBJ);620entry.pushKV("txid", out.outpoint.hash.GetHex());621entry.pushKV("vout", out.outpoint.n);623if (fValidAddress) {624entry.pushKV("address", EncodeDestination(address));626const auto* address_book_entry = pwallet->FindAddressBookEntry(address);627if (address_book_entry) {628entry.pushKV("label", address_book_entry->GetLabel());629}631std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);632if (provider) {633if (scriptPubKey.IsPayToScriptHash()) {634const CScriptID hash = ToScriptID(std::get<ScriptHash>(address));635CScript redeemScript;636if (provider->GetCScript(hash, redeemScript)) {637entry.pushKV("redeemScript", HexStr(redeemScript));638// Now check if the redeemScript is actually a P2WSH script639CTxDestination witness_destination;640if (redeemScript.IsPayToWitnessScriptHash()) {641bool extracted = ExtractDestination(redeemScript, witness_destination);642CHECK_NONFATAL(extracted);643// Also return the witness script644const WitnessV0ScriptHash& whash = std::get<WitnessV0ScriptHash>(witness_destination);645CScriptID id{RIPEMD160(whash)};646CScript witnessScript;647if (provider->GetCScript(id, witnessScript)) {648entry.pushKV("witnessScript", HexStr(witnessScript));649}650}651}652} else if (scriptPubKey.IsPayToWitnessScriptHash()) {653const WitnessV0ScriptHash& whash = std::get<WitnessV0ScriptHash>(address);654CScriptID id{RIPEMD160(whash)};655CScript witnessScript;656if (provider->GetCScript(id, witnessScript)) {657entry.pushKV("witnessScript", HexStr(witnessScript));658}659}660}661}663entry.pushKV("scriptPubKey", HexStr(scriptPubKey));664entry.pushKV("amount", ValueFromAmount(out.txout.nValue));665entry.pushKV("confirmations", out.depth);666if (!out.depth) {667size_t ancestor_count, unused_cluster_count, ancestor_size;668CAmount ancestor_fees;669pwallet->chain().getTransactionAncestry(out.outpoint.hash, ancestor_count, unused_cluster_count, &ancestor_size, &ancestor_fees);670if (ancestor_count) {671entry.pushKV("ancestorcount", ancestor_count);672entry.pushKV("ancestorsize", ancestor_size);673entry.pushKV("ancestorfees", ancestor_fees);674}675}676entry.pushKV("spendable", true); // Any coins we list are always spendable677entry.pushKV("solvable", out.solvable);678if (out.solvable) {679std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);680if (provider) {681auto descriptor = InferDescriptor(scriptPubKey, *provider);682entry.pushKV("desc", descriptor->ToString());683}684}685PushParentDescriptors(*pwallet, scriptPubKey, entry);686if (avoid_reuse) entry.pushKV("reused", reused);687entry.pushKV("safe", out.safe);688results.push_back(std::move(entry));689}691return results;692},693};694}695} // namespace wallet