70 const CCoinControl* coin_control,
const bool tx_is_segwit,
71 const bool can_grind_r) {
74 const bool is_segwit =
IsSegwit(desc);
82 const int64_t witstack_len = is_segwit ?
GetSizeOfCompactSize(*elems_count) : (tx_is_segwit ? 1 : 0);
97 if (
const auto weight =
MaxInputWeight(*desc,
CTxIn{outpoint}, coin_control,
true, can_grind_r)) {
116 for (
const auto spkman:
wallet->GetScriptPubKeyMans(script_pubkey)) {
117 providers.
AddProvider(spkman->GetSolvingProvider(script_pubkey));
127 const CTxIn& txin,
const CTxOut& txo,
const bool tx_is_segwit,
128 const bool can_grind_r)
131 std::optional<int64_t> weight;
133 return weight.value();
138 if (desc)
return MaxInputWeight(*desc, {txin}, coin_control, tx_is_segwit, can_grind_r);
150 bool is_segwit = std::any_of(txouts.begin(), txouts.end(), [&](
const CTxOut& txo) {
151 std::unique_ptr<Descriptor> desc{GetDescriptor(wallet, coin_control, txo.scriptPubKey)};
156 if (is_segwit) weight += 2;
162 for (uint32_t i = 0; i < txouts.size(); i++) {
164 if (!txin_weight)
return TxSize{-1, -1};
165 assert(*txin_weight > -1);
166 weight += *txin_weight;
175 std::vector<CTxOut> txouts;
180 if (mi !=
wallet->mapWallet.end()) {
182 txouts.emplace_back(mi->second.GetTx()->vout.at(input.
prevout.
n));
183 }
else if (coin_control) {
185 if (!txout)
return TxSize{-1, -1};
186 txouts.emplace_back(*txout);
194size_t CoinsResult::Size()
const
197 for (
const auto& it : coins) {
198 size += it.second.size();
203std::vector<COutput> CoinsResult::All()
const
205 std::vector<COutput> all;
207 for (
const auto& it : coins) {
208 all.insert(all.end(), it.second.begin(), it.second.end());
213void CoinsResult::Erase(
const std::unordered_set<COutPoint, SaltedOutpointHasher>& coins_to_remove)
215 for (
auto& [type, vec] : coins) {
216 auto remove_it = std::remove_if(vec.begin(), vec.end(), [&](
const COutput& coin) {
218 if (!coins_to_remove.contains(coin.outpoint)) return false;
221 total_amount -= coin.txout.nValue;
222 if (coin.HasEffectiveValue() && total_effective_amount.has_value()) total_effective_amount = *total_effective_amount - coin.GetEffectiveValue();
225 vec.erase(remove_it, vec.end());
231 for (
auto& it : coins) {
232 std::shuffle(it.second.begin(), it.second.end(), rng_fast);
238 coins[type].emplace_back(
out);
239 total_amount +=
out.txout.nValue;
240 if (
out.HasEffectiveValue()) {
241 total_effective_amount = total_effective_amount.has_value() ?
242 *total_effective_amount +
out.GetEffectiveValue() :
out.GetEffectiveValue();
269 const bool can_grind_r =
wallet.CanGrindR();
272 int64_t input_bytes = coin_control.
GetInputWeight(outpoint).value_or(-1);
273 if (input_bytes != -1) {
277 if (
auto txo =
wallet.GetTXO(outpoint)) {
278 txout = txo->GetTxOut();
279 if (input_bytes == -1) {
282 const CWalletTx& parent_tx = txo->GetWalletTx();
283 if (
wallet.GetTxDepthInMainChain(parent_tx) == 0) {
287 return util::Error{
strprintf(
_(
"Can't spend unconfirmed version %d pre-selected input with a version 3 tx"), parent_tx.
GetTx()->version)};
300 if (input_bytes == -1) {
304 if (input_bytes == -1) {
318 std::optional<CFeeRate> feerate,
325 std::vector<std::pair<OutputType, COutput>> unconfirmed_truc_coins;
326 std::unordered_map<Txid, CAmount, SaltedTxidHasher> truc_txid_by_value;
333 const bool can_grind_r =
wallet.CanGrindR();
334 std::vector<COutPoint> outpoints;
336 std::set<Txid> trusted_parents;
338 std::unordered_map<Txid, std::pair<bool, bool>,
SaltedTxidHasher> tx_safe_cache;
339 for (
const auto& [outpoint, txo] :
wallet.GetTXOs()) {
340 const CWalletTx& wtx = txo.GetWalletTx();
341 const CTxOut& output = txo.GetTxOut();
343 if (tx_safe_cache.contains(outpoint.hash) && !tx_safe_cache.at(outpoint.hash).first) {
347 int nDepth =
wallet.GetTxDepthInMainChain(wtx);
350 if (!tx_safe_cache.contains(outpoint.hash)) {
351 tx_safe_cache[outpoint.hash] = {
false,
false};
404 size_t ancestors, unused_cluster_count;
405 wallet.chain().getTransactionAncestry(wtx.
GetTx()->GetHash(), ancestors, unused_cluster_count);
406 if (ancestors > 1)
continue;
412 if (only_safe && !safeTx) {
416 if (nDepth < min_depth || nDepth > max_depth) {
420 tx_safe_cache[outpoint.hash] = {
true, safeTx};
422 const auto& [tx_ok, tx_safe] = tx_safe_cache.at(outpoint.hash);
437 if (
wallet.IsSpent(outpoint))
451 bool solvable = input_bytes > -1;
454 std::vector<std::vector<uint8_t>> script_solutions;
461 bool is_from_p2sh{
false};
469 auto available_output_type =
GetOutputType(type, is_from_p2sh);
470 auto available_output =
COutput(outpoint, output, nDepth, input_bytes, solvable, tx_safe, wtx.
GetTxTime(), tx_from_me, feerate);
472 unconfirmed_truc_coins.emplace_back(available_output_type, available_output);
473 auto [it,
_] = truc_txid_by_value.try_emplace(wtx.
GetTx()->GetHash(), 0);
474 it->second += output.
nValue;
476 result.
Add(available_output_type, available_output);
479 outpoints.push_back(outpoint);
499 auto highest_value_truc_tx = std::max_element(truc_txid_by_value.begin(), truc_txid_by_value.end(), [](
const auto& tx1,
const auto& tx2){
500 return tx1.second < tx2.second;
503 const Txid& truc_txid = highest_value_truc_tx->first;
504 for (
const auto& [type, output] : unconfirmed_truc_coins) {
505 if (output.outpoint.hash == truc_txid) {
506 result.
Add(type, output);
511 if (feerate.has_value()) {
512 std::map<COutPoint, CAmount> map_of_bump_fees =
wallet.chain().calculateIndividualBumpFees(outpoints, feerate.value());
514 for (
auto& [
_, outputs] : result.
coins) {
515 for (
auto& output : outputs) {
516 output.ApplyBumpFee(map_of_bump_fees.at(output.outpoint));
534 if (!it || it->
GetTx()->vout.size() <= prevout.
n ||
538 ptx = it->
GetTx().get();
548 std::map<CTxDestination, std::vector<COutput>> result;
557 if (
auto pk_dest = std::get_if<PubKeyDestination>(&address)) {
558 address =
PKHash(pk_dest->GetPubKey());
563 result[address].emplace_back(coin);
571 const std::vector<SelectionFilter>& filters,
572 std::vector<OutputGroup>& ret_discarded_groups)
578 for (
const auto& [type, outputs] : coins.
coins) {
579 for (
const COutput& output : outputs) {
581 size_t ancestors, cluster_count;
582 wallet.chain().getTransactionAncestry(output.outpoint.hash, ancestors, cluster_count);
586 group.Insert(std::make_shared<COutput>(output), ancestors, cluster_count);
589 bool accepted =
false;
590 for (
const auto& sel_filter : filters) {
591 const auto& filter = sel_filter.filter;
592 if (!
group.EligibleForSpending(filter))
continue;
593 filtered_groups[filter].Push(
group, type,
true,
true);
596 if (!accepted) ret_discarded_groups.emplace_back(
group);
599 return filtered_groups;
608 typedef std::map<std::pair<CScript, OutputType>, std::vector<OutputGroup>> ScriptPubKeyToOutgroup;
609 const auto& insert_output = [&](
610 const std::shared_ptr<COutput>& output,
OutputType type,
size_t ancestors,
size_t cluster_count,
611 ScriptPubKeyToOutgroup& groups_map) {
612 std::vector<OutputGroup>& groups = groups_map[std::make_pair(output->txout.scriptPubKey,type)];
614 if (groups.size() == 0) {
616 groups.emplace_back(coin_sel_params);
627 groups.emplace_back(coin_sel_params);
628 group = &groups.back();
631 group->Insert(output, ancestors, cluster_count);
634 ScriptPubKeyToOutgroup spk_to_groups_map;
635 ScriptPubKeyToOutgroup spk_to_positive_groups_map;
636 for (
const auto& [type, outs] : coins.
coins) {
637 for (
const COutput& output : outs) {
638 size_t ancestors, cluster_count;
639 wallet.chain().getTransactionAncestry(output.outpoint.hash, ancestors, cluster_count);
641 const auto& shared_output = std::make_shared<COutput>(output);
643 if (output.GetEffectiveValue() > 0) {
644 insert_output(shared_output, type, ancestors, cluster_count, spk_to_positive_groups_map);
648 insert_output(shared_output, type, ancestors, cluster_count, spk_to_groups_map);
653 const auto& push_output_groups = [&](
const ScriptPubKeyToOutgroup& groups_map,
bool positive_only) {
654 for (
const auto& [
script, groups] : groups_map) {
656 for (
auto group_it = groups.rbegin(); group_it != groups.rend(); group_it++) {
660 bool accepted =
false;
661 for (
const auto& sel_filter : filters) {
662 const auto& filter = sel_filter.filter;
663 if (!
group.EligibleForSpending(filter))
continue;
666 if (group_it == groups.rbegin() && groups.size() > 1 && !filter.m_include_partial_groups) {
672 filtered_groups[filter].Push(
group, type, positive_only, !positive_only);
676 if (!accepted && !positive_only) ret_discarded_groups.emplace_back(
group);
681 push_output_groups(spk_to_groups_map,
false);
682 push_output_groups(spk_to_positive_groups_map,
true);
684 return filtered_groups;
690 const std::vector<SelectionFilter>& filters)
692 std::vector<OutputGroup> unused;
703 std::vector<SelectionResult> results;
709 if (result) results.push_back(*result);
713 if (results.size() > 0)
return *std::min_element(results.begin(), results.end());
718 if (allow_mixed_output_types && groups.
TypesCount() > 1) {
729 std::vector<SelectionResult> results;
730 std::vector<util::Result<SelectionResult>> errors;
735 errors.emplace_back(std::move(result));
742 int max_selection_weight = max_transaction_weight - tx_weight_no_input;
743 if (max_selection_weight <= 0) {
744 return util::Error{
_(
"Maximum transaction weight is less than transaction weight without inputs")};
750 results.push_back(*bnb_result);
751 }
else append_error(std::move(bnb_result));
756 max_selection_weight -= change_outputs_weight;
757 if (max_selection_weight < 0 && results.empty()) {
758 return util::Error{
_(
"Maximum transaction weight is too low, can not accommodate change output")};
763 results.push_back(*knapsack_result);
764 }
else append_error(std::move(knapsack_result));
769 results.push_back(*cg_result);
771 append_error(std::move(cg_result));
776 results.push_back(*srd_result);
777 }
else append_error(std::move(srd_result));
779 if (results.empty()) {
782 return errors.empty() ?
util::Error() : std::move(errors.front());
786 for (
auto& result : results) {
787 std::vector<COutPoint> outpoints;
790 for (
auto& coin : coins) {
791 if (coin->depth > 0)
continue;
792 outpoints.push_back(coin->outpoint);
793 summed_bump_fees += coin->ancestor_bump_fees;
796 if (!combined_bump_fee.has_value()) {
797 return util::Error{
_(
"Failed to calculate bump fees, because unconfirmed UTXOs depend on an enormous cluster of unconfirmed transactions.")};
799 CAmount bump_fee_overestimate = summed_bump_fees - combined_bump_fee.value();
801 if (bump_fee_overestimate > 0) {
802 result.SetBumpFeeDiscount(bump_fee_overestimate);
809 return *std::min_element(results.begin(), results.end());
821 return util::Error{
_(
"The preselected coins total amount does not cover the transaction target. "
822 "Please allow other inputs to be automatically selected or include more coins manually")};
826 for (
const auto& output: pre_set_inputs.
All()) {
827 preset_coin_set.insert(std::make_shared<COutput>(output));
831 if (selection_target <= 0) {
841 if (selection_target > available_coins_total_amount) {
847 if (!op_selection_result)
return op_selection_result;
850 if (!pre_set_inputs.
coins.empty()) {
852 assert(preset_total.has_value());
853 SelectionResult preselected(preset_total.value(), SelectionAlgorithm::MANUAL);
855 op_selection_result->Merge(preselected);
862 if (op_selection_result->GetWeight() > max_inputs_weight) {
863 return util::Error{
_(
"The combination of the pre-selected inputs and the wallet automatic inputs selection exceeds the transaction maximum weight. "
864 "Please try sending a smaller amount or manually consolidating your wallet's UTXOs")};
867 return op_selection_result;
877 unsigned int limit_ancestor_count = 0;
878 unsigned int limit_descendant_count = 0;
879 wallet.chain().getPackageLimits(limit_ancestor_count, limit_descendant_count);
880 const size_t max_ancestors = (size_t)std::max<int64_t>(1, limit_ancestor_count);
881 const size_t max_cluster_count = (size_t)std::max<int64_t>(1, limit_descendant_count);
896 std::vector<SelectionFilter> ordered_filters{
904 if (
wallet.m_spend_zero_conf_change) {
906 ordered_filters.push_back({
CoinEligibilityFilter(0, 1, std::min(
size_t{4}, max_ancestors/3), std::min(
size_t{4}, max_cluster_count/3))});
911 ordered_filters.push_back({
CoinEligibilityFilter(0, 1, max_ancestors-1, max_cluster_count-1,
true)});
915 ordered_filters.push_back({
CoinEligibilityFilter(0, 0, max_ancestors-1, max_cluster_count-1,
true)});
921 if (!fRejectLongChains) {
923 std::numeric_limits<uint64_t>::max(),
929 std::vector<OutputGroup> discarded_groups;
934 CAmount total_unconf_long_chain = 0;
935 for (
const auto&
group : discarded_groups) {
936 total_discarded +=
group.GetSelectionAmount();
937 if (
group.m_ancestors >= max_ancestors ||
group.m_max_cluster_count >= max_cluster_count) total_unconf_long_chain +=
group.GetSelectionAmount();
940 if (
CAmount total_amount = available_coins.
GetTotalAmount() - total_discarded; total_amount < value_to_select) {
942 if (total_amount + total_unconf_long_chain > value_to_select) {
943 return util::Error{
_(
"Unconfirmed UTXOs are available, but spending them creates a chain of transactions that will be rejected by the mempool")};
951 std::vector<util::Result<SelectionResult>> res_detailed_errors;
953 for (
const auto& select_filter : ordered_filters) {
954 auto it = filtered_groups.find(select_filter.filter);
955 if (it == filtered_groups.end())
continue;
956 if (updated_selection_params.
m_version ==
TRUC_VERSION && (select_filter.filter.conf_mine == 0 || select_filter.filter.conf_theirs == 0)) {
962 updated_selection_params, select_filter.allow_mixed_output_types)}) {
968 if (
HasErrorMsg(res)) res_detailed_errors.emplace_back(std::move(res));
973 if (!res_detailed_errors.empty())
return std::move(res_detailed_errors.front());
986 constexpr int64_t MAX_ANTI_FEE_SNIPING_TIP_AGE = 8 * 60 * 60;
989 if (block_time < (
GetTime() - MAX_ANTI_FEE_SNIPING_TIP_AGE)) {
1039 for (
const auto& in : tx.
vin) {
1063 const std::vector<CRecipient>& vecSend,
1064 std::optional<unsigned int> change_pos,
1073 txNew.
version = coin_control.m_version;
1076 coin_selection_params.m_avoid_partial_spends = coin_control.m_avoid_partial_spends;
1077 coin_selection_params.m_include_unsafe_inputs = coin_control.m_include_unsafe_inputs;
1079 coin_selection_params.m_version = coin_control.m_version;
1081 if (coin_selection_params.m_max_tx_weight.value() < minimum_tx_weight || coin_selection_params.m_max_tx_weight.value() >
MAX_STANDARD_TX_WEIGHT) {
1085 coin_selection_params.m_long_term_feerate =
wallet.m_consolidate_feerate;
1090 const OutputType change_type =
wallet.TransactionChangeType(coin_control.m_change_type ? *coin_control.m_change_type :
wallet.m_default_change_type, vecSend);
1092 unsigned int outputs_to_subtract_fee_from = 0;
1093 for (
const auto& recipient : vecSend) {
1094 if (
IsDust(recipient,
wallet.chain().relayDustFee())) {
1100 recipients_sum += recipient.nAmount;
1102 if (recipient.fSubtractFeeFromAmount) {
1103 outputs_to_subtract_fee_from++;
1104 coin_selection_params.m_subtract_fee_outputs =
true;
1113 if (!std::get_if<CNoDestination>(&coin_control.destChange)) {
1138 CTxOut change_prototype_txout(0, scriptChange);
1139 coin_selection_params.change_output_size =
GetSerializeSize(change_prototype_txout);
1145 if (change_spend_size == -1) {
1148 coin_selection_params.change_spend_size = change_spend_size;
1156 coin_selection_params.m_effective_feerate = min_fee_rate.
fee_rate;
1159 if (coin_control.m_feerate && coin_selection_params.m_effective_feerate > *coin_control.m_feerate) {
1161 auto msg{
strprintf(
_(
"Fee rate (%s) is lower than the minimum fee rate setting (%s)."),
1162 coin_control.m_feerate->ToString(feerate_format),
1163 coin_selection_params.m_effective_feerate.ToString(feerate_format))};
1165 msg +=
strprintf(
_(
"\nConsider modifying %s (%s) or %s (%s)."),
1167 wallet.m_min_fee.ToString(feerate_format),
1169 wallet.chain().relayMinFee().ToString(feerate_format));
1175 return util::Error{
strprintf(
_(
"Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable %s."),
"-fallbackfee")};
1183 coin_selection_params.m_change_fee = coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.change_output_size);
1184 coin_selection_params.m_cost_of_change = coin_selection_params.m_discard_feerate.GetFee(coin_selection_params.change_spend_size) + coin_selection_params.m_change_fee;
1186 coin_selection_params.m_min_change_target =
GenerateChangeTarget(std::floor(recipients_sum / vecSend.size()), coin_selection_params.m_change_fee, rng_fast);
1191 const auto dust =
GetDustThreshold(change_prototype_txout, coin_selection_params.m_discard_feerate);
1192 const auto change_spend_fee = coin_selection_params.m_discard_feerate.GetFee(coin_selection_params.change_spend_size);
1193 coin_selection_params.min_viable_change = std::max(change_spend_fee + 1, dust);
1196 const CAmount not_input_fees = coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.m_subtract_fee_outputs ? 0 : coin_selection_params.tx_noinputs_size);
1197 CAmount selection_target = recipients_sum + not_input_fees;
1201 if (selection_target == 0 && !coin_control.HasSelected()) {
1202 return util::Error{
_(
"Transaction requires one destination of non-zero value, a non-zero feerate, or a pre-selected input")};
1207 if (coin_control.HasSelected()) {
1210 preset_inputs = *res_fetch_inputs;
1216 if (coin_control.m_allow_other_inputs) {
1217 available_coins =
AvailableCoins(
wallet, &coin_control, coin_selection_params.m_effective_feerate);
1221 auto select_coins_res =
SelectCoins(
wallet, available_coins, preset_inputs, selection_target, coin_control, coin_selection_params);
1222 if (!select_coins_res) {
1231 if (available_balance >= recipients_sum) {
1236 if (available_effective_balance < selection_target) {
1237 Assume(!coin_selection_params.m_subtract_fee_outputs);
1238 return util::Error{
strprintf(
_(
"The total exceeds your balance when the %s transaction fee is included."),
FormatMoney(selection_target - recipients_sum))};
1247 wallet.GetName().c_str(),
1254 txNew.
vout.reserve(vecSend.size() + 1);
1255 for (
const auto& recipient : vecSend)
1259 const CAmount change_amount = result.
GetChange(coin_selection_params.min_viable_change, coin_selection_params.m_change_fee);
1260 if (change_amount > 0) {
1261 CTxOut newTxOut(change_amount, scriptChange);
1265 }
else if ((
unsigned int)*change_pos > txNew.
vout.size()) {
1266 return util::Error{
_(
"Transaction change output index out of range")};
1268 txNew.
vout.insert(txNew.
vout.begin() + *change_pos, newTxOut);
1270 change_pos = std::nullopt;
1276 if (coin_control.HasSelected() && coin_control.HasSelectedOrder()) {
1281 std::stable_sort(selected_coins.begin(), selected_coins.end(),
1282 [&coin_control](
const std::shared_ptr<COutput>& a,
const std::shared_ptr<COutput>& b) {
1283 auto a_pos = coin_control.GetSelectionPos(a->outpoint);
1284 auto b_pos = coin_control.GetSelectionPos(b->outpoint);
1285 if (a_pos.has_value() && b_pos.has_value()) {
1286 return a_pos.value() < b_pos.value();
1287 }
else if (a_pos.has_value() && !b_pos.has_value()) {
1303 bool use_anti_fee_sniping =
true;
1305 txNew.vin.reserve(selected_coins.size());
1306 for (
const auto& coin : selected_coins) {
1307 std::optional<uint32_t>
sequence = coin_control.GetSequence(coin->outpoint);
1310 use_anti_fee_sniping =
false;
1312 txNew.vin.emplace_back(coin->outpoint,
CScript{},
sequence.value_or(default_sequence));
1314 auto scripts = coin_control.GetScripts(coin->outpoint);
1315 if (scripts.first) {
1316 txNew.vin.back().scriptSig = *scripts.first;
1318 if (scripts.second) {
1319 txNew.vin.back().scriptWitness = *scripts.second;
1322 if (coin_control.m_locktime) {
1323 txNew.nLockTime = coin_control.m_locktime.value();
1325 use_anti_fee_sniping =
false;
1327 if (use_anti_fee_sniping) {
1333 int nBytes = tx_sizes.vsize;
1335 return util::Error{
_(
"Missing solving data for estimating transaction size")};
1337 CAmount fee_needed = coin_selection_params.m_effective_feerate.GetFee(nBytes) + result.GetTotalBumpFees();
1339 Assume(recipients_sum + change_amount == output_value);
1340 CAmount current_fee = result.GetSelectedValue() - output_value;
1343 if (current_fee < 0) {
1348 if (change_pos && fee_needed < current_fee) {
1349 auto& change = txNew.vout.at(*change_pos);
1350 change.nValue += current_fee - fee_needed;
1352 if (fee_needed != current_fee) {
1358 if (coin_selection_params.m_subtract_fee_outputs) {
1359 CAmount to_reduce = fee_needed - current_fee;
1362 for (
const auto& recipient : vecSend)
1364 if (change_pos && i == *change_pos) {
1367 CTxOut& txout = txNew.vout[i];
1369 if (recipient.fSubtractFeeFromAmount)
1371 txout.
nValue -= to_reduce / outputs_to_subtract_fee_from;
1376 txout.
nValue -= to_reduce % outputs_to_subtract_fee_from;
1382 return util::Error{
_(
"The transaction amount is too small to pay the fee")};
1384 return util::Error{
_(
"The transaction amount is too small to send after the fee has been deducted")};
1391 if (fee_needed != current_fee) {
1398 if (fee_needed > current_fee) {
1403 if (scriptChange.empty() && change_pos) {
1407 if (
sign && !
wallet.SignTransaction(txNew)) {
1421 if (current_fee >
wallet.m_max_tx_fee) {
1426 if (current_fee >
wallet.m_max_tx_fee_rate.GetFee(tx_vsize)) {
1432 auto result =
wallet.chain().checkChainLimits(tx);
1440 reservedest.KeepDestination();
1442 wallet.WalletLogPrintf(
"Coin Selection: Algorithm:%s, Waste Metric Score:%d\n",
GetAlgorithmName(result.GetAlgo()), result.GetWaste());
1443 wallet.WalletLogPrintf(
"Fee Calculation: Fee:%d Bytes:%u, Source: %s\n",
1445 return CreatedTransactionResult(tx, current_fee, change_pos, min_fee_rate.fee_reason);
1450 const std::vector<CRecipient>& vecSend,
1451 std::optional<unsigned int> change_pos,
1455 if (vecSend.empty()) {
1456 return util::Error{
_(
"Transaction must have at least one recipient")};
1459 if (std::any_of(vecSend.cbegin(), vecSend.cend(), [](
const auto& recipient){ return recipient.nAmount < 0; })) {
1460 return util::Error{
_(
"Transaction amounts must not be negative")};
1466 TRACEPOINT(coin_selection, normal_create_tx_internal,
1467 wallet.GetName().c_str(),
1470 res && res->change_pos.has_value() ? int32_t(*res->change_pos) : -1);
1471 if (!res)
return res;
1472 const auto& txr_ungrouped = *res;
1475 TRACEPOINT(coin_selection, attempting_aps_create_tx,
wallet.GetName().c_str());
1480 if (txr_ungrouped.change_pos) {
1486 const bool use_aps{txr_grouped.has_value() ? (txr_grouped->fee <= txr_ungrouped.fee +
wallet.m_max_aps_fee) :
false};
1487 TRACEPOINT(coin_selection, aps_create_tx_internal,
1488 wallet.GetName().c_str(),
1490 txr_grouped.has_value(),
1491 txr_grouped.has_value() ? txr_grouped->fee : 0,
1492 txr_grouped.has_value() && txr_grouped->change_pos.has_value() ? int32_t(*txr_grouped->change_pos) : -1);
1494 wallet.WalletLogPrintf(
"Fee non-grouped = %lld, grouped = %lld, using %s\n",
1495 txr_ungrouped.fee, txr_grouped->fee, use_aps ?
"grouped" :
"non-grouped");
1496 if (use_aps)
return txr_grouped;
1520 std::map<COutPoint, Coin> coins;
1524 wallet.chain().findCoins(coins);
1527 const auto& outPoint = txin.
prevout;
1529 if (!
wallet.IsMine(outPoint)) {
1530 if (coins[outPoint].
out.IsNull()) {
1531 return util::Error{
_(
"Unable to find UTXO for external input")};
1548 for (
const CTxIn& txin : res->tx->vin) {
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
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.
constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
int64_t CAmount
Amount in satoshis (Can be negative)
#define CHECK_NONFATAL(condition)
Identity function.
#define Assert(val)
Identity function.
#define STR_INTERNAL_BUG(msg)
#define Assume(val)
Assume is the identity function.
bool GetBoolArg(const std::string &strArg, bool fDefault) const EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
Return boolean argument or default value.
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac.
An outpoint - a combination of a transaction hash and an index n into its vout.
Serialized script, used inside transaction inputs and outputs.
A reference to a CScript: the Hash160 of its serialization.
The basic transaction that is broadcasted on the network and contained in blocks.
const std::vector< CTxOut > vout
const std::vector< CTxIn > vin
An input of a transaction.
static constexpr uint32_t SEQUENCE_FINAL
Setting nSequence to this value for every input in a transaction disables nLockTime/IsFinalTx().
CScriptWitness scriptWitness
Only serialized through CTransaction.
static constexpr uint32_t MAX_SEQUENCE_NONFINAL
This is the maximum sequence number that enables both nLockTime and OP_CHECKLOCKTIMEVERIFY (BIP 65).
An output of a transaction.
A signing provider to be used to interface with multiple signing providers at once.
void AddProvider(std::unique_ptr< SigningProvider > provider)
I randrange(I range) noexcept
Generate a random integer in the range [0..range), with range > 0.
An interface to be implemented by keystores that support signing.
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
virtual bool isInitialBlockDownload()=0
Check if in IBD.
virtual std::optional< CAmount > calculateCombinedBumpFee(const std::vector< COutPoint > &outpoints, const CFeeRate &target_feerate)=0
Calculate the combined bump fee for an input set per the same strategy.
virtual bool findBlock(const uint256 &hash, const FoundBlock &block={})=0
Return whether node has the block and optionally return block metadata or contents.
Helper for findBlock to selectively return pieces of block data.
bool IsSelected(const COutPoint &outpoint) const
Returns true if the given output is pre-selected.
std::optional< CTxOut > GetExternalOutput(const COutPoint &outpoint) const
Returns the external output for the given outpoint if it exists.
bool m_avoid_address_reuse
Forbids inclusion of dirty (previously used) addresses.
std::optional< int64_t > GetInputWeight(const COutPoint &outpoint) const
Returns the input weight.
PreselectedInput & Select(const COutPoint &outpoint)
Lock-in the given output for spending.
bool HasSelected() const
Returns true if there are pre-selected inputs.
bool IsExternalSelected(const COutPoint &outpoint) const
Returns true if the given output is selected as an external input.
int m_min_depth
Minimum chain depth value for coin availability.
bool m_allow_other_inputs
If true, the selection process can add extra unselected inputs from the wallet while requires all sel...
int m_max_depth
Maximum chain depth value for coin availability.
bool m_include_unsafe_inputs
If false, only safe inputs will be used.
bool m_avoid_partial_spends
Avoid partial use of funds sent to a given address.
uint32_t m_version
Version.
FlatSigningProvider m_external_provider
SigningProvider that has pubkeys and scripts to do spend size estimation for external inputs.
CTxDestination destChange
Custom change destination, if not set an address is generated.
std::vector< COutPoint > ListSelected() const
List the selected inputs.
std::optional< uint32_t > m_locktime
Locktime.
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
A transaction with a bunch of additional info that only the owner cares about.
std::optional< Txid > m_replaces_txid
std::optional< Txid > m_replaced_by_txid
std::optional< Txid > truc_child_in_mempool
int64_t GetTxTime() const
CTransactionRef GetTx() const
A wrapper to reserve an address from a wallet.
util::Result< CTxDestination > GetReservedDestination(bool internal)
Reserve an address.
static int32_t GetTransactionWeight(const CTransaction &tx)
constexpr int WITNESS_SCALE_FACTOR
@ SAT_VB
Use sat/vB fee rate unit.
is a home for simple string functions returning descriptive messages that are used in RPC and GUI int...
std::string FormatMoney(const CAmount n)
Money parsing/formatting utilities.
static int sign(const secp256k1_context *ctx, struct signer_secrets *signer_secrets, struct signer *signer, const secp256k1_musig_keyagg_cache *cache, const unsigned char *msg32, unsigned char *sig64)
bilingual_str TransactionErrorString(const TransactionError err)
std::string StringForFeeReason(FeeReason reason)
bilingual_str ErrorString(const Result< T > &result)
constexpr size_t DUMMY_NESTED_P2WPKH_INPUT_SIZE
Pre-calculated constants for input size estimation in virtual size
const CTxOut & FindNonChangeParentOutput(const CWallet &wallet, const COutPoint &outpoint)
Find non-change parent output.
bool OutputIsChange(const CWallet &wallet, const CTxOut &txout)
constexpr bool DEFAULT_WALLET_REJECT_LONG_CHAINS
Default for -walletrejectlongchains.
util::Result< SelectionResult > AutomaticCoinSelection(const CWallet &wallet, CoinsResult &available_coins, const CAmount &value_to_select, const CoinSelectionParams &coin_selection_params)
Select a set of coins such that nTargetValue is met; never select unconfirmed coins if they are not o...
util::Result< CreatedTransactionResult > FundTransaction(CWallet &wallet, const CMutableTransaction &tx, const std::vector< CRecipient > &vecSend, std::optional< unsigned int > change_pos, bool lockUnspents, CCoinControl coinControl)
Insert additional inputs into the transaction by calling CreateTransaction();.
util::Result< CreatedTransactionResult > CreateTransaction(CWallet &wallet, const std::vector< CRecipient > &vecSend, std::optional< unsigned int > change_pos, const CCoinControl &coin_control, bool sign)
Create a new transaction paying the recipients with a set of coins selected by SelectCoins(); Also cr...
bool CachedTxIsFromMe(const CWallet &wallet, const CWalletTx &wtx)
util::Result< CoinsResult > FetchSelectedInputs(const CWallet &wallet, const CCoinControl &coin_control, const CoinSelectionParams &coin_selection_params)
Fetch and validate coin control selected inputs.
bool CachedTxIsTrusted(const CWallet &wallet, const CWalletTx &wtx, std::set< Txid > &trusted_parents)
MinimumFeeRateResult GetMinimumFeeRate(const CWallet &wallet, const CCoinControl &coin_control)
Estimate the minimum fee rate considering user set parameters and the required fee.
util::Result< SelectionResult > SelectCoinsBnB(std::vector< OutputGroup > &utxo_pool, const CAmount &selection_target, const CAmount &cost_of_change, int max_selection_weight)
static std::unique_ptr< Descriptor > GetDescriptor(const CWallet *wallet, const CCoinControl *coin_control, const CScript script_pubkey)
Infer a descriptor for the given output script.
static bool UseMaxSig(const std::optional< CTxIn > &txin, const CCoinControl *coin_control)
Whether to assume ECDSA signatures' will be high-r.
static std::optional< int64_t > GetSignedTxinWeight(const CWallet *wallet, const CCoinControl *coin_control, const CTxIn &txin, const CTxOut &txo, const bool tx_is_segwit, const bool can_grind_r)
Infer the maximum size of this input after it will be signed.
util::Result< SelectionResult > CoinGrinder(std::vector< OutputGroup > &utxo_pool, const CAmount &selection_target, CAmount change_target, int max_selection_weight)
bool IsDust(const CRecipient &recipient, const CFeeRate &dustRelayFee)
static OutputType GetOutputType(TxoutType type, bool is_from_p2sh)
static bool IsSegwit(const Descriptor &desc)
Whether the descriptor represents, directly or not, a witness program.
std::set< std::shared_ptr< COutput >, OutputPtrComparator > OutputSet
util::Result< SelectionResult > AttemptSelection(interfaces::Chain &chain, const CAmount &nTargetValue, OutputGroupTypeMap &groups, const CoinSelectionParams &coin_selection_params, bool allow_mixed_output_types)
Attempt to find a valid input set that preserves privacy by not mixing OutputTypes.
util::Result< SelectionResult > ChooseSelectionResult(interfaces::Chain &chain, const CAmount &nTargetValue, Groups &groups, const CoinSelectionParams &coin_selection_params)
Attempt to find a valid input set that meets the provided eligibility filter and target.
util::Result< SelectionResult > KnapsackSolver(std::vector< OutputGroup > &groups, const CAmount &nTargetValue, CAmount change_target, FastRandomContext &rng, int max_selection_weight)
util::Result< SelectionResult > SelectCoins(const CWallet &wallet, CoinsResult &available_coins, const CoinsResult &pre_set_inputs, const CAmount &nTargetValue, const CCoinControl &coin_control, const CoinSelectionParams &coin_selection_params)
Select all coins from coin_control, and if coin_control 'm_allow_other_inputs=true',...
constexpr int DEFAULT_MAX_DEPTH
CAmount GenerateChangeTarget(const CAmount payment_value, const CAmount change_fee, FastRandomContext &rng)
Choose a random change target for each transaction to make it harder to fingerprint the Core wallet b...
std::map< CTxDestination, std::vector< COutput > > ListCoins(const CWallet &wallet)
Return list of available coins and locked coins grouped by non-change output address.
int CalculateMaximumSignedInputSize(const CTxOut &txout, const CWallet *wallet, const CCoinControl *coin_control)
Get the marginal bytes if spending the specified output from this transaction.
std::string GetAlgorithmName(const SelectionAlgorithm algo)
void DiscourageFeeSniping(CMutableTransaction &tx, FastRandomContext &rng_fast, interfaces::Chain &chain, const uint256 &block_hash, int block_height)
Set a height-based locktime for new transactions (uses the height of the current chain tip unless we ...
TxSize CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const CCoinControl *coin_control)
static bool HasErrorMsg(const util::Result< SelectionResult > &res)
CFeeRate GetDiscardRate(const CWallet &wallet)
Return the maximum feerate for discarding change.
std::map< CoinEligibilityFilter, OutputGroupTypeMap > FilteredOutputGroups
TxSize CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector< CTxOut > &txouts, const CCoinControl *coin_control)
Calculate the size of the transaction using CoinControl to determine whether to expect signature grin...
static util::Result< CreatedTransactionResult > CreateTransactionInternal(CWallet &wallet, const std::vector< CRecipient > &vecSend, std::optional< unsigned int > change_pos, const CCoinControl &coin_control, bool sign) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
@ WALLET_FLAG_AVOID_REUSE
static bool IsCurrentForAntiFeeSniping(interfaces::Chain &chain, const uint256 &block_hash)
constexpr int DEFAULT_MIN_DEPTH
FilteredOutputGroups GroupOutputs(const CWallet &wallet, const CoinsResult &coins, const CoinSelectionParams ¶ms, const std::vector< SelectionFilter > &filters)
Group coins by the provided filters.
static constexpr size_t OUTPUT_GROUP_MAX_ENTRIES
int CalculateMaximumSignedInputSize(const CTxOut &txout, const COutPoint outpoint, const SigningProvider *provider, bool can_grind_r, const CCoinControl *coin_control)
static std::optional< int64_t > MaxInputWeight(const Descriptor &desc, const std::optional< CTxIn > &txin, const CCoinControl *coin_control, const bool tx_is_segwit, const bool can_grind_r)
Get the size of an input (in witness units) once it's signed.
util::Result< SelectionResult > SelectCoinsSRD(const std::vector< OutputGroup > &utxo_pool, CAmount target_value, CAmount change_fee, FastRandomContext &rng, int max_selection_weight)
Select coins by Single Random Draw (SRD).
uint64_t GetSerializeSizeForRecipient(const CRecipient &recipient)
is a home for public enum and struct type definitions that are used internally by node code,...
CAmount GetDustThreshold(const CTxOut &txout, const CFeeRate &dustRelayFeeIn)
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost, unsigned int bytes_per_sigop)
Compute the virtual transaction size (weight reinterpreted as bytes).
constexpr unsigned int MIN_STANDARD_TX_NONWITNESS_SIZE
The minimum non-witness size for transactions we're willing to relay/mine: one larger than 64
constexpr int32_t MAX_STANDARD_TX_WEIGHT
The maximum weight for transactions we're willing to relay/mine.
CAmount CalculateOutputValue(const TxType &tx)
static CTransactionRef MakeTransactionRef(Tx &&txIn)
std::shared_ptr< const CTransaction > CTransactionRef
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible.
constexpr unsigned int LOCKTIME_THRESHOLD
constexpr unsigned int GetSizeOfCompactSize(uint64_t nSize)
Compact Size size < 253 – 1 byte size <= USHRT_MAX – 3 bytes (253 + 2 bytes) size <= UINT_MAX – 5 byt...
uint64_t GetSerializeSize(const T &t)
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< unsigned char > > &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
TRACEPOINT_SEMAPHORE(coin_selection, selected_coins)
A mutable version of CTransaction.
std::vector< CTxOut > vout
Interface for parsed descriptor objects.
virtual std::optional< int64_t > MaxSatisfactionElems() const =0
Get the maximum size number of stack elements for satisfying this descriptor.
virtual std::optional< int64_t > MaxSatisfactionWeight(bool use_max_sig) const =0
Get the maximum size of a satisfaction for this descriptor, in weight units.
virtual std::optional< OutputType > GetOutputType() const =0
A UTXO under consideration for use in funding a new transaction.
COutPoint outpoint
The outpoint identifying this UTXO.
void ApplyBumpFee(CAmount bump_fee)
Parameters for filtering which OutputGroups we may use in coin selection.
bool check_version_trucness
bool include_immature_coinbase
Parameters for one iteration of Coin Selection.
uint32_t m_version
The version of the transaction we are trying to create.
FastRandomContext & rng_fast
Randomness to use in the context of coin selection.
CAmount m_min_change_target
Mininmum change to target in Knapsack solver and CoinGrinder: select coins to cover the payment and a...
bool m_subtract_fee_outputs
Indicate that we are subtracting the fee from outputs.
bool m_include_unsafe_inputs
When true, allow unsafe coins to be selected during Coin Selection.
CFeeRate m_effective_feerate
The targeted feerate of the transaction being built.
CAmount min_viable_change
Minimum amount for creating a change output.
CAmount m_cost_of_change
Cost of creating the change output + cost of spending the change output in the future.
CAmount m_change_fee
Cost of creating the change output.
int change_output_size
Size of a change output in bytes, determined by the output type.
int tx_noinputs_size
Size of the transaction before coin selection, consisting of the header and recipient output(s),...
std::optional< int > m_max_tx_weight
The maximum weight for this transaction.
bool m_avoid_partial_spends
When true, always spend all (up to OUTPUT_GROUP_MAX_ENTRIES) or none of the outputs associated with t...
COutputs available for spending, stored by OutputType.
std::optional< CAmount > GetAppropriateTotal(bool subtract_fee_outputs) const
void Add(OutputType type, const COutput &out)
std::vector< COutput > All() const
Concatenate and return all COutputs as one vector.
std::optional< CAmount > GetEffectiveTotalAmount() const
CAmount GetTotalAmount() const
size_t Size() const
The following methods are provided so that CoinsResult can mimic a vector, i.e., methods can work wit...
std::map< OutputType, std::vector< COutput > > coins
void Shuffle(FastRandomContext &rng_fast)
std::vector< OutputGroup > positive_group
std::vector< OutputGroup > mixed_group
A group of UTXOs paid to the same output script.
Stores several 'Groups' whose were mapped by output type.
std::map< OutputType, Groups > groups_by_type
void AddInputs(const OutputSet &inputs, bool subtract_fee_outputs)
CAmount GetChange(CAmount min_viable_change, CAmount change_fee) const
Get the amount for the change output after paying needed fees.
void RecalculateWaste(CAmount min_viable_change, CAmount change_cost, CAmount change_fee)
Calculates and stores the waste for this result given the cost of change and the opportunity cost of ...
CAmount GetSelectedValue() const
Get the sum of the input values.
CAmount GetTarget() const
SelectionAlgorithm GetAlgo() const
std::vector< std::shared_ptr< COutput > > GetShuffledInputVector() const
Get the vector of COutputs that will be used to fill in a CTransaction's vin.
FuzzedDataProvider provider
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define TRACEPOINT(context,...)
consteval auto _(util::TranslatedLiteral str)
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
constexpr decltype(CTransaction::version) TRUC_VERSION
constexpr int64_t TRUC_CHILD_MAX_WEIGHT
constexpr uint32_t MAX_BIP125_RBF_SEQUENCE
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
static void AvailableCoins(benchmark::Bench &bench, const std::vector< OutputType > &output_type)