Inside Bitcoin
Opening the selected file…
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.
251case TxoutType::WITNESS_V0_KEYHASH:252case TxoutType::WITNESS_V0_SCRIPTHASH:253if (is_from_p2sh) return OutputType::P2SH_SEGWIT;254else return OutputType::BECH32;255case TxoutType::SCRIPTHASH:256case TxoutType::PUBKEYHASH:257return OutputType::LEGACY;258default:259return OutputType::UNKNOWN;260}261}263// Fetch and validate the coin control selected inputs.264// Coins could be internal (from the wallet) or external.265util::Result<CoinsResult> FetchSelectedInputs(const CWallet& wallet, const CCoinControl& coin_control,266const CoinSelectionParams& coin_selection_params)267{268CoinsResult result;269const bool can_grind_r = wallet.CanGrindR();270std::map<COutPoint, CAmount> map_of_bump_fees = wallet.chain().calculateIndividualBumpFees(coin_control.ListSelected(), coin_selection_params.m_effective_feerate);271for (const COutPoint& outpoint : coin_control.ListSelected()) {272int64_t input_bytes = coin_control.GetInputWeight(outpoint).value_or(-1);273if (input_bytes != -1) {274input_bytes = GetVirtualTransactionSize(input_bytes, 0, 0);275}276CTxOut txout;277if (auto txo = wallet.GetTXO(outpoint)) {278txout = txo->GetTxOut();279if (input_bytes == -1) {280input_bytes = CalculateMaximumSignedInputSize(txout, &wallet, &coin_control);281}282const CWalletTx& parent_tx = txo->GetWalletTx();283if (wallet.GetTxDepthInMainChain(parent_tx) == 0) {284if (parent_tx.GetTx()->version == TRUC_VERSION && coin_control.m_version != TRUC_VERSION) {285return util::Error{strprintf(_("Can't spend unconfirmed version 3 pre-selected input with a version %d tx"), coin_control.m_version)};286} else if (coin_control.m_version == TRUC_VERSION && parent_tx.GetTx()->version != TRUC_VERSION) {287return util::Error{strprintf(_("Can't spend unconfirmed version %d pre-selected input with a version 3 tx"), parent_tx.GetTx()->version)};288}289}290} else {291// The input is external. We did not find the tx in mapWallet.292const auto out{coin_control.GetExternalOutput(outpoint)};293if (!out) {294return util::Error{strprintf(_("Not found pre-selected input %s"), outpoint.ToString())};295}297txout = *out;298}300if (input_bytes == -1) {301input_bytes = CalculateMaximumSignedInputSize(txout, outpoint, &coin_control.m_external_provider, can_grind_r, &coin_control);302}304if (input_bytes == -1) {305return util::Error{strprintf(_("Not solvable pre-selected input %s"), outpoint.ToString())}; // Not solvable, can't estimate size for fee306}308/* Set some defaults for depth, solvable, safe, time, and from_me as these don't matter for preset inputs since no selection is being done. */309COutput output(outpoint, txout, /*depth=*/0, input_bytes, /*solvable=*/true, /*safe=*/true, /*time=*/0, /*from_me=*/false, coin_selection_params.m_effective_feerate);310output.ApplyBumpFee(map_of_bump_fees.at(output.outpoint));311result.Add(OutputType::UNKNOWN, output);312}313return result;314}316CoinsResult AvailableCoins(const CWallet& wallet,317const CCoinControl* coinControl,318std::optional<CFeeRate> feerate,319const CoinFilterParams& params)320{321AssertLockHeld(wallet.cs_wallet);323CoinsResult result;324// track unconfirmed truc outputs separately if we are tracking trucness325std::vector<std::pair<OutputType, COutput>> unconfirmed_truc_coins;326std::unordered_map<Txid, CAmount, SaltedTxidHasher> truc_txid_by_value;327// Either the WALLET_FLAG_AVOID_REUSE flag is not set (in which case we always allow), or we default to avoiding, and only in the case where328// a coin control object is provided, and has the avoid address reuse flag set to false, do we allow already used addresses329bool allow_used_addresses = !wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE) || (coinControl && !coinControl->m_avoid_address_reuse);330const int min_depth = {coinControl ? coinControl->m_min_depth : DEFAULT_MIN_DEPTH};331const int max_depth = {coinControl ? coinControl->m_max_depth : DEFAULT_MAX_DEPTH};332const bool only_safe = {coinControl ? !coinControl->m_include_unsafe_inputs : true};333const bool can_grind_r = wallet.CanGrindR();334std::vector<COutPoint> outpoints;336std::set<Txid> trusted_parents;337// Cache for whether each tx passes the tx level checks (first bool), and whether the transaction is "safe" (second bool)338std::unordered_map<Txid, std::pair<bool, bool>, SaltedTxidHasher> tx_safe_cache;339for (const auto& [outpoint, txo] : wallet.GetTXOs()) {340const CWalletTx& wtx = txo.GetWalletTx();341const CTxOut& output = txo.GetTxOut();343if (tx_safe_cache.contains(outpoint.hash) && !tx_safe_cache.at(outpoint.hash).first) {344continue;345}347int nDepth = wallet.GetTxDepthInMainChain(wtx);349// Perform tx level checks if we haven't already come across outputs from this tx before.350if (!tx_safe_cache.contains(outpoint.hash)) {351tx_safe_cache[outpoint.hash] = {false, false};353if (wallet.IsTxImmatureCoinBase(wtx) && !params.include_immature_coinbase)354continue;356if (nDepth < 0)357continue;359// We should not consider coins which aren't at least in our mempool360// It's possible for these to be conflicted via ancestors which we may never be able to detect361if (nDepth == 0 && !wtx.InMempool())362continue;364bool safeTx = CachedTxIsTrusted(wallet, wtx, trusted_parents);366// We should not consider coins from transactions that are replacing367// other transactions.368//369// Example: There is a transaction A which is replaced by bumpfee370// transaction B. In this case, we want to prevent creation of371// a transaction B' which spends an output of B.372//373// Reason: If transaction A were initially confirmed, transactions B374// and B' would no longer be valid, so the user would have to create375// a new transaction C to replace B'. However, in the case of a376// one-block reorg, transactions B' and C might BOTH be accepted,377// when the user only wanted one of them. Specifically, there could378// be a 1-block reorg away from the chain where transactions A and C379// were accepted to another chain where B, B', and C were all380// accepted.381if (nDepth == 0 && wtx.m_replaces_txid) {382safeTx = false;383}385// Similarly, we should not consider coins from transactions that386// have been replaced. In the example above, we would want to prevent387// creation of a transaction A' spending an output of A, because if388// transaction B were initially confirmed, conflicting with A and389// A', we wouldn't want to the user to create a transaction D390// intending to replace A', but potentially resulting in a scenario391// where A, A', and D could all be accepted (instead of just B and392// D, or just A and A' like the user would want).393if (nDepth == 0 && wtx.m_replaced_by_txid) {394safeTx = false;395}397if (nDepth == 0 && params.check_version_trucness) {398if (coinControl->m_version == TRUC_VERSION) {399if (wtx.GetTx()->version != TRUC_VERSION) continue;400// this unconfirmed v3 transaction already has a child401if (wtx.truc_child_in_mempool.has_value()) continue;403// this unconfirmed v3 transaction has a parent: spending would create a third generation404size_t ancestors, unused_cluster_count;405wallet.chain().getTransactionAncestry(wtx.GetTx()->GetHash(), ancestors, unused_cluster_count);406if (ancestors > 1) continue;407} else {408if (wtx.GetTx()->version == TRUC_VERSION) continue;409}410}412if (only_safe && !safeTx) {413continue;414}416if (nDepth < min_depth || nDepth > max_depth) {417continue;418}420tx_safe_cache[outpoint.hash] = {true, safeTx};421}422const auto& [tx_ok, tx_safe] = tx_safe_cache.at(outpoint.hash);423if (!Assume(tx_ok)) {424continue;425}427if (output.nValue < params.min_amount || output.nValue > params.max_amount)428continue;430// Skip manually selected coins (the caller can fetch them directly)431if (coinControl && coinControl->HasSelected() && coinControl->IsSelected(outpoint))432continue;434if (wallet.IsLockedCoin(outpoint) && params.skip_locked)435continue;437if (wallet.IsSpent(outpoint))438continue;440if (!allow_used_addresses && wallet.IsSpentKey(output.scriptPubKey)) {441continue;442}444bool tx_from_me = CachedTxIsFromMe(wallet, wtx);446std::unique_ptr<SigningProvider> provider = wallet.GetSolvingProvider(output.scriptPubKey);448int input_bytes = CalculateMaximumSignedInputSize(output, COutPoint(), provider.get(), can_grind_r, coinControl);449// Because CalculateMaximumSignedInputSize infers a solvable descriptor to get the satisfaction size,450// it is safe to assume that this input is solvable if input_bytes is greater than -1.451bool solvable = input_bytes > -1;453// Obtain script type454std::vector<std::vector<uint8_t>> script_solutions;455TxoutType type = Solver(output.scriptPubKey, script_solutions);457// If the output is P2SH and solvable, we want to know if it is458// a P2SH (legacy) or one of P2SH-P2WPKH, P2SH-P2WSH (P2SH-Segwit). We can determine459// this from the redeemScript. If the output is not solvable, it will be classified460// as a P2SH (legacy), since we have no way of knowing otherwise without the redeemScript461bool is_from_p2sh{false};462if (type == TxoutType::SCRIPTHASH && solvable) {463CScript script;464if (!provider->GetCScript(CScriptID(uint160(script_solutions[0])), script)) continue;465type = Solver(script, script_solutions);466is_from_p2sh = true;467}469auto available_output_type = GetOutputType(type, is_from_p2sh);470auto available_output = COutput(outpoint, output, nDepth, input_bytes, solvable, tx_safe, wtx.GetTxTime(), tx_from_me, feerate);471if (wtx.GetTx()->version == TRUC_VERSION && nDepth == 0 && params.check_version_trucness) {472unconfirmed_truc_coins.emplace_back(available_output_type, available_output);473auto [it, _] = truc_txid_by_value.try_emplace(wtx.GetTx()->GetHash(), 0);474it->second += output.nValue;475} else {476result.Add(available_output_type, available_output);477}479outpoints.push_back(outpoint);481// Checks the sum amount of all UTXO's.482if (params.min_sum_amount != MAX_MONEY) {483if (result.GetTotalAmount() >= params.min_sum_amount) {484return result;485}486}488// Checks the maximum number of UTXO's.489if (params.max_count > 0 && result.Size() >= params.max_count) {490return result;491}492}494// Return all the coins from one TRUC transaction, that have the highest value.495// This could be improved in the future by encoding these restrictions in496// the coin selection itself so that we don't have to filter out497// other unconfirmed TRUC coins beforehand.498if (params.check_version_trucness && unconfirmed_truc_coins.size() > 0) {499auto highest_value_truc_tx = std::max_element(truc_txid_by_value.begin(), truc_txid_by_value.end(), [](const auto& tx1, const auto& tx2){500return tx1.second < tx2.second;