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);
94 if (!provider)
return -1;
97 if (
const auto weight =
MaxInputWeight(*desc, {}, coin_control,
true, can_grind_r)) {
107 const std::unique_ptr<SigningProvider> provider =
wallet->GetSolvingProvider(txout.
scriptPubKey);
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) {
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.tx->vout.at(input.
prevout.
n));
183 }
else if (coin_control) {
185 if (!txout)
return TxSize{-1, -1};
186 txouts.emplace_back(*txout);
197 for (
const auto& it :
coins) {
198 size += it.second.size();
205 std::vector<COutput> all;
207 for (
const auto& it :
coins) {
208 all.insert(all.end(), it.second.begin(), it.second.end());
219 for (
auto& [type, vec] :
coins) {
220 auto remove_it = std::remove_if(vec.begin(), vec.end(), [&](
const COutput& coin) {
222 if (!coins_to_remove.contains(coin.outpoint))
return false;
229 vec.erase(remove_it, vec.end());
235 for (
auto& it :
coins) {
236 std::shuffle(it.second.begin(), it.second.end(), rng_fast);
244 if (
out.HasEffectiveValue()) {
273 const bool can_grind_r =
wallet.CanGrindR();
276 int64_t input_bytes = coin_control.
GetInputWeight(outpoint).value_or(-1);
277 if (input_bytes != -1) {
281 if (
auto txo =
wallet.GetTXO(outpoint)) {
282 txout = txo->GetTxOut();
283 if (input_bytes == -1) {
286 const CWalletTx& parent_tx = txo->GetWalletTx();
287 if (
wallet.GetTxDepthInMainChain(parent_tx) == 0) {
291 return util::Error{
strprintf(
_(
"Can't spend unconfirmed version %d pre-selected input with a version 3 tx"), parent_tx.
tx->version)};
304 if (input_bytes == -1) {
308 if (input_bytes == -1) {
322 std::optional<CFeeRate> feerate,
329 std::vector<std::pair<OutputType, COutput>> unconfirmed_truc_coins;
330 std::unordered_map<Txid, CAmount, SaltedTxidHasher> truc_txid_by_value;
337 const bool can_grind_r =
wallet.CanGrindR();
338 std::vector<COutPoint> outpoints;
340 std::set<Txid> trusted_parents;
342 std::unordered_map<Txid, std::pair<bool, bool>,
SaltedTxidHasher> tx_safe_cache;
343 for (
const auto& [outpoint, txo] :
wallet.GetTXOs()) {
344 const CWalletTx& wtx = txo.GetWalletTx();
345 const CTxOut& output = txo.GetTxOut();
347 if (tx_safe_cache.contains(outpoint.hash) && !tx_safe_cache.at(outpoint.hash).first) {
351 int nDepth =
wallet.GetTxDepthInMainChain(wtx);
354 if (!tx_safe_cache.contains(outpoint.hash)) {
355 tx_safe_cache[outpoint.hash] = {
false,
false};
385 if (nDepth == 0 && wtx.
mapValue.contains(
"replaces_txid")) {
397 if (nDepth == 0 && wtx.
mapValue.contains(
"replaced_by_txid")) {
408 size_t ancestors, unused_cluster_count;
409 wallet.chain().getTransactionAncestry(wtx.
tx->GetHash(), ancestors, unused_cluster_count);
410 if (ancestors > 1)
continue;
416 if (only_safe && !safeTx) {
420 if (nDepth < min_depth || nDepth > max_depth) {
424 tx_safe_cache[outpoint.hash] = {
true, safeTx};
426 const auto& [tx_ok, tx_safe] = tx_safe_cache.at(outpoint.hash);
441 if (
wallet.IsSpent(outpoint))
450 std::unique_ptr<SigningProvider> provider =
wallet.GetSolvingProvider(output.
scriptPubKey);
455 bool solvable = input_bytes > -1;
458 std::vector<std::vector<uint8_t>> script_solutions;
465 bool is_from_p2sh{
false};
473 auto available_output_type =
GetOutputType(type, is_from_p2sh);
474 auto available_output =
COutput(outpoint, output, nDepth, input_bytes, solvable, tx_safe, wtx.
GetTxTime(), tx_from_me, feerate);
476 unconfirmed_truc_coins.emplace_back(available_output_type, available_output);
477 auto [it,
_] = truc_txid_by_value.try_emplace(wtx.
tx->GetHash(), 0);
478 it->second += output.
nValue;
480 result.Add(available_output_type, available_output);
483 outpoints.push_back(outpoint);
503 auto highest_value_truc_tx = std::max_element(truc_txid_by_value.begin(), truc_txid_by_value.end(), [](
const auto& tx1,
const auto& tx2){
504 return tx1.second < tx2.second;
507 const Txid& truc_txid = highest_value_truc_tx->first;
508 for (
const auto& [type, output] : unconfirmed_truc_coins) {
509 if (output.outpoint.hash == truc_txid) {
515 if (feerate.has_value()) {
516 std::map<COutPoint, CAmount> map_of_bump_fees =
wallet.chain().calculateIndividualBumpFees(outpoints, feerate.value());
518 for (
auto& [
_, outputs] :
result.coins) {
519 for (
auto& output : outputs) {
520 output.ApplyBumpFee(map_of_bump_fees.at(output.outpoint));
538 if (!it || it->
tx->vout.size() <= prevout.
n ||
539 !
wallet.IsMine(it->
tx->vout[prevout.
n])) {
552 std::map<CTxDestination, std::vector<COutput>>
result;
561 if (
auto pk_dest = std::get_if<PubKeyDestination>(&address)) {
562 address =
PKHash(pk_dest->GetPubKey());
567 result[address].emplace_back(coin);
575 const std::vector<SelectionFilter>& filters,
576 std::vector<OutputGroup>& ret_discarded_groups)
582 for (
const auto& [type, outputs] : coins.
coins) {
583 for (
const COutput& output : outputs) {
585 size_t ancestors, cluster_count;
586 wallet.chain().getTransactionAncestry(output.outpoint.hash, ancestors, cluster_count);
590 group.Insert(std::make_shared<COutput>(output), ancestors, cluster_count);
593 bool accepted =
false;
594 for (
const auto& sel_filter : filters) {
595 const auto& filter = sel_filter.filter;
596 if (!
group.EligibleForSpending(filter))
continue;
597 filtered_groups[filter].Push(
group, type,
true,
true);
600 if (!accepted) ret_discarded_groups.emplace_back(
group);
603 return filtered_groups;
612 typedef std::map<std::pair<CScript, OutputType>, std::vector<OutputGroup>> ScriptPubKeyToOutgroup;
613 const auto& insert_output = [&](
614 const std::shared_ptr<COutput>& output,
OutputType type,
size_t ancestors,
size_t cluster_count,
615 ScriptPubKeyToOutgroup& groups_map) {
616 std::vector<OutputGroup>& groups = groups_map[std::make_pair(output->txout.scriptPubKey,type)];
618 if (groups.size() == 0) {
620 groups.emplace_back(coin_sel_params);
631 groups.emplace_back(coin_sel_params);
632 group = &groups.back();
635 group->Insert(output, ancestors, cluster_count);
638 ScriptPubKeyToOutgroup spk_to_groups_map;
639 ScriptPubKeyToOutgroup spk_to_positive_groups_map;
640 for (
const auto& [type, outs] : coins.
coins) {
641 for (
const COutput& output : outs) {
642 size_t ancestors, cluster_count;
643 wallet.chain().getTransactionAncestry(output.outpoint.hash, ancestors, cluster_count);
645 const auto& shared_output = std::make_shared<COutput>(output);
647 if (output.GetEffectiveValue() > 0) {
648 insert_output(shared_output, type, ancestors, cluster_count, spk_to_positive_groups_map);
652 insert_output(shared_output, type, ancestors, cluster_count, spk_to_groups_map);
657 const auto& push_output_groups = [&](
const ScriptPubKeyToOutgroup& groups_map,
bool positive_only) {
658 for (
const auto& [
script, groups] : groups_map) {
660 for (
auto group_it = groups.rbegin(); group_it != groups.rend(); group_it++) {
664 bool accepted =
false;
665 for (
const auto& sel_filter : filters) {
666 const auto& filter = sel_filter.filter;
667 if (!
group.EligibleForSpending(filter))
continue;
670 if (group_it == groups.rbegin() && groups.size() > 1 && !filter.m_include_partial_groups) {
676 filtered_groups[filter].Push(
group, type, positive_only, !positive_only);
679 if (!accepted) ret_discarded_groups.emplace_back(
group);
684 push_output_groups(spk_to_groups_map,
false);
685 push_output_groups(spk_to_positive_groups_map,
true);
687 return filtered_groups;
693 const std::vector<SelectionFilter>& filters)
695 std::vector<OutputGroup> unused;
706 std::vector<SelectionResult> results;
716 if (results.size() > 0)
return *std::min_element(results.begin(), results.end());
721 if (allow_mixed_output_types && groups.
TypesCount() > 1) {
732 std::vector<SelectionResult> results;
733 std::vector<util::Result<SelectionResult>> errors;
738 errors.emplace_back(std::move(
result));
745 int max_selection_weight = max_transaction_weight - tx_weight_no_input;
746 if (max_selection_weight <= 0) {
747 return util::Error{
_(
"Maximum transaction weight is less than transaction weight without inputs")};
753 results.push_back(*bnb_result);
754 }
else append_error(std::move(bnb_result));
759 max_selection_weight -= change_outputs_weight;
760 if (max_selection_weight < 0 && results.empty()) {
761 return util::Error{
_(
"Maximum transaction weight is too low, can not accommodate change output")};
766 results.push_back(*knapsack_result);
767 }
else append_error(std::move(knapsack_result));
772 results.push_back(*cg_result);
774 append_error(std::move(cg_result));
779 results.push_back(*srd_result);
780 }
else append_error(std::move(srd_result));
782 if (results.empty()) {
785 return errors.empty() ?
util::Error() : std::move(errors.front());
789 for (
auto&
result : results) {
790 std::vector<COutPoint> outpoints;
793 for (
auto& coin : coins) {
794 if (coin->depth > 0)
continue;
795 outpoints.push_back(coin->outpoint);
796 summed_bump_fees += coin->ancestor_bump_fees;
799 if (!combined_bump_fee.has_value()) {
800 return util::Error{
_(
"Failed to calculate bump fees, because unconfirmed UTXOs depend on an enormous cluster of unconfirmed transactions.")};
802 CAmount bump_fee_overestimate = summed_bump_fees - combined_bump_fee.value();
803 if (bump_fee_overestimate) {
804 result.SetBumpFeeDiscount(bump_fee_overestimate);
811 return *std::min_element(results.begin(), results.end());
823 return util::Error{
_(
"The preselected coins total amount does not cover the transaction target. " 824 "Please allow other inputs to be automatically selected or include more coins manually")};
828 for (
const auto& output: pre_set_inputs.
All()) {
829 preset_coin_set.insert(std::make_shared<COutput>(output));
833 if (selection_target <= 0) {
843 if (selection_target > available_coins_total_amount) {
849 if (!op_selection_result)
return op_selection_result;
852 if (!pre_set_inputs.
coins.empty()) {
854 assert(preset_total.has_value());
857 op_selection_result->Merge(preselected);
864 if (op_selection_result->GetWeight() > max_inputs_weight) {
865 return util::Error{
_(
"The combination of the pre-selected inputs and the wallet automatic inputs selection exceeds the transaction maximum weight. " 866 "Please try sending a smaller amount or manually consolidating your wallet's UTXOs")};
869 return op_selection_result;
879 unsigned int limit_ancestor_count = 0;
880 unsigned int limit_descendant_count = 0;
881 wallet.chain().getPackageLimits(limit_ancestor_count, limit_descendant_count);
882 const size_t max_ancestors = (size_t)std::max<int64_t>(1, limit_ancestor_count);
883 const size_t max_cluster_count = (size_t)std::max<int64_t>(1, limit_descendant_count);
898 std::vector<SelectionFilter> ordered_filters{
906 if (
wallet.m_spend_zero_conf_change) {
908 ordered_filters.push_back({
CoinEligibilityFilter(0, 1, std::min(
size_t{4}, max_ancestors/3), std::min(
size_t{4}, max_cluster_count/3))});
913 ordered_filters.push_back({
CoinEligibilityFilter(0, 1, max_ancestors-1, max_cluster_count-1,
true)});
917 ordered_filters.push_back({
CoinEligibilityFilter(0, 0, max_ancestors-1, max_cluster_count-1,
true)});
923 if (!fRejectLongChains) {
925 std::numeric_limits<uint64_t>::max(),
931 std::vector<OutputGroup> discarded_groups;
936 CAmount total_unconf_long_chain = 0;
937 for (
const auto&
group : discarded_groups) {
938 total_discarded +=
group.GetSelectionAmount();
939 if (
group.m_ancestors >= max_ancestors ||
group.m_max_cluster_count >= max_cluster_count) total_unconf_long_chain +=
group.GetSelectionAmount();
942 if (
CAmount total_amount = available_coins.
GetTotalAmount() - total_discarded; total_amount < value_to_select) {
944 if (total_amount + total_unconf_long_chain > value_to_select) {
945 return util::Error{
_(
"Unconfirmed UTXOs are available, but spending them creates a chain of transactions that will be rejected by the mempool")};
953 std::vector<util::Result<SelectionResult>> res_detailed_errors;
955 for (
const auto& select_filter : ordered_filters) {
956 auto it = filtered_groups.find(select_filter.filter);
957 if (it == filtered_groups.end())
continue;
958 if (updated_selection_params.
m_version ==
TRUC_VERSION && (select_filter.filter.conf_mine == 0 || select_filter.filter.conf_theirs == 0)) {
964 updated_selection_params, select_filter.allow_mixed_output_types)}) {
970 if (
HasErrorMsg(res)) res_detailed_errors.emplace_back(std::move(res));
975 if (!res_detailed_errors.empty())
return std::move(res_detailed_errors.front());
988 constexpr int64_t MAX_ANTI_FEE_SNIPING_TIP_AGE = 8 * 60 * 60;
991 if (block_time < (
GetTime() - MAX_ANTI_FEE_SNIPING_TIP_AGE)) {
1041 for (
const auto& in : tx.
vin) {
1065 const std::vector<CRecipient>& vecSend,
1066 std::optional<unsigned int> change_pos,
1075 txNew.
version = coin_control.m_version;
1078 coin_selection_params.m_avoid_partial_spends = coin_control.m_avoid_partial_spends;
1079 coin_selection_params.m_include_unsafe_inputs = coin_control.m_include_unsafe_inputs;
1081 coin_selection_params.m_version = coin_control.m_version;
1083 if (coin_selection_params.m_max_tx_weight.value() < minimum_tx_weight || coin_selection_params.m_max_tx_weight.value() >
MAX_STANDARD_TX_WEIGHT) {
1087 coin_selection_params.m_long_term_feerate =
wallet.m_consolidate_feerate;
1092 const OutputType change_type =
wallet.TransactionChangeType(coin_control.m_change_type ? *coin_control.m_change_type :
wallet.m_default_change_type, vecSend);
1094 unsigned int outputs_to_subtract_fee_from = 0;
1095 for (
const auto& recipient : vecSend) {
1096 if (
IsDust(recipient,
wallet.chain().relayDustFee())) {
1102 recipients_sum += recipient.nAmount;
1104 if (recipient.fSubtractFeeFromAmount) {
1105 outputs_to_subtract_fee_from++;
1106 coin_selection_params.m_subtract_fee_outputs =
true;
1115 if (!std::get_if<CNoDestination>(&coin_control.destChange)) {
1140 CTxOut change_prototype_txout(0, scriptChange);
1141 coin_selection_params.change_output_size =
GetSerializeSize(change_prototype_txout);
1147 if (change_spend_size == -1) {
1150 coin_selection_params.change_spend_size = change_spend_size;
1161 if (coin_control.m_feerate && coin_selection_params.m_effective_feerate > *coin_control.m_feerate) {
1166 return util::Error{
strprintf(
_(
"Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable %s."),
"-fallbackfee")};
1174 coin_selection_params.m_change_fee = coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.change_output_size);
1175 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;
1177 coin_selection_params.m_min_change_target =
GenerateChangeTarget(std::floor(recipients_sum / vecSend.size()), coin_selection_params.m_change_fee, rng_fast);
1182 const auto dust =
GetDustThreshold(change_prototype_txout, coin_selection_params.m_discard_feerate);
1183 const auto change_spend_fee = coin_selection_params.m_discard_feerate.GetFee(coin_selection_params.change_spend_size);
1184 coin_selection_params.min_viable_change = std::max(change_spend_fee + 1, dust);
1187 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);
1188 CAmount selection_target = recipients_sum + not_input_fees;
1192 if (selection_target == 0 && !coin_control.HasSelected()) {
1193 return util::Error{
_(
"Transaction requires one destination of non-zero value, a non-zero feerate, or a pre-selected input")};
1198 if (coin_control.HasSelected()) {
1201 preset_inputs = *res_fetch_inputs;
1207 if (coin_control.m_allow_other_inputs) {
1208 available_coins =
AvailableCoins(
wallet, &coin_control, coin_selection_params.m_effective_feerate);
1212 auto select_coins_res =
SelectCoins(
wallet, available_coins, preset_inputs, selection_target, coin_control, coin_selection_params);
1213 if (!select_coins_res) {
1222 if (available_balance >= recipients_sum) {
1227 if (available_effective_balance < selection_target) {
1228 Assume(!coin_selection_params.m_subtract_fee_outputs);
1229 return util::Error{
strprintf(
_(
"The total exceeds your balance when the %s transaction fee is included."),
FormatMoney(selection_target - recipients_sum))};
1238 wallet.GetName().c_str(),
1242 result.GetSelectedValue());
1245 txNew.
vout.reserve(vecSend.size() + 1);
1246 for (
const auto& recipient : vecSend)
1250 const CAmount change_amount =
result.GetChange(coin_selection_params.min_viable_change, coin_selection_params.m_change_fee);
1251 if (change_amount > 0) {
1252 CTxOut newTxOut(change_amount, scriptChange);
1256 }
else if ((
unsigned int)*change_pos > txNew.
vout.size()) {
1257 return util::Error{
_(
"Transaction change output index out of range")};
1259 txNew.
vout.insert(txNew.
vout.begin() + *change_pos, newTxOut);
1261 change_pos = std::nullopt;
1265 std::vector<std::shared_ptr<COutput>> selected_coins =
result.GetShuffledInputVector();
1267 if (coin_control.HasSelected() && coin_control.HasSelectedOrder()) {
1272 std::stable_sort(selected_coins.begin(), selected_coins.end(),
1273 [&coin_control](
const std::shared_ptr<COutput>& a,
const std::shared_ptr<COutput>& b) {
1274 auto a_pos = coin_control.GetSelectionPos(a->outpoint);
1275 auto b_pos = coin_control.GetSelectionPos(b->outpoint);
1276 if (a_pos.has_value() && b_pos.has_value()) {
1277 return a_pos.value() < b_pos.value();
1278 }
else if (a_pos.has_value() && !b_pos.has_value()) {
1294 bool use_anti_fee_sniping =
true;
1296 txNew.
vin.reserve(selected_coins.size());
1297 for (
const auto& coin : selected_coins) {
1298 std::optional<uint32_t>
sequence = coin_control.GetSequence(coin->outpoint);
1301 use_anti_fee_sniping =
false;
1303 txNew.
vin.emplace_back(coin->outpoint,
CScript{},
sequence.value_or(default_sequence));
1305 auto scripts = coin_control.GetScripts(coin->outpoint);
1306 if (scripts.first) {
1307 txNew.
vin.back().scriptSig = *scripts.first;
1309 if (scripts.second) {
1310 txNew.
vin.back().scriptWitness = *scripts.second;
1313 if (coin_control.m_locktime) {
1314 txNew.
nLockTime = coin_control.m_locktime.value();
1316 use_anti_fee_sniping =
false;
1318 if (use_anti_fee_sniping) {
1324 int nBytes = tx_sizes.
vsize;
1326 return util::Error{
_(
"Missing solving data for estimating transaction size")};
1328 CAmount fee_needed = coin_selection_params.m_effective_feerate.GetFee(nBytes) +
result.GetTotalBumpFees();
1330 Assume(recipients_sum + change_amount == output_value);
1331 CAmount current_fee =
result.GetSelectedValue() - output_value;
1334 if (current_fee < 0) {
1339 if (change_pos && fee_needed < current_fee) {
1340 auto& change = txNew.
vout.at(*change_pos);
1341 change.nValue += current_fee - fee_needed;
1343 if (fee_needed != current_fee) {
1349 if (coin_selection_params.m_subtract_fee_outputs) {
1350 CAmount to_reduce = fee_needed - current_fee;
1353 for (
const auto& recipient : vecSend)
1355 if (change_pos && i == *change_pos) {
1360 if (recipient.fSubtractFeeFromAmount)
1362 txout.
nValue -= to_reduce / outputs_to_subtract_fee_from;
1367 txout.
nValue -= to_reduce % outputs_to_subtract_fee_from;
1373 return util::Error{
_(
"The transaction amount is too small to pay the fee")};
1375 return util::Error{
_(
"The transaction amount is too small to send after the fee has been deducted")};
1382 if (fee_needed != current_fee) {
1389 if (fee_needed > current_fee) {
1394 if (scriptChange.
empty() && change_pos) {
1398 if (
sign && !
wallet.SignTransaction(txNew)) {
1412 if (current_fee >
wallet.m_default_max_tx_fee) {
1429 wallet.WalletLogPrintf(
"Fee Calculation: Fee:%d Bytes:%u Tgt:%d (requested %d) Reason:\"%s\" Decay %.5f: Estimation: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out) Fail: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out)\n",
1442 const std::vector<CRecipient>& vecSend,
1443 std::optional<unsigned int> change_pos,
1447 if (vecSend.empty()) {
1448 return util::Error{
_(
"Transaction must have at least one recipient")};
1451 if (std::any_of(vecSend.cbegin(), vecSend.cend(), [](
const auto& recipient){
return recipient.nAmount < 0; })) {
1452 return util::Error{
_(
"Transaction amounts must not be negative")};
1458 TRACEPOINT(coin_selection, normal_create_tx_internal,
1459 wallet.GetName().c_str(),
1462 res && res->change_pos.has_value() ? int32_t(*res->change_pos) : -1);
1463 if (!res)
return res;
1464 const auto& txr_ungrouped = *res;
1467 TRACEPOINT(coin_selection, attempting_aps_create_tx,
wallet.GetName().c_str());
1472 if (txr_ungrouped.change_pos) {
1473 ExtractDestination(txr_ungrouped.tx->vout[*txr_ungrouped.change_pos].scriptPubKey, tmp_cc.destChange);
1478 const bool use_aps{txr_grouped.has_value() ? (txr_grouped->fee <= txr_ungrouped.fee +
wallet.m_max_aps_fee) :
false};
1479 TRACEPOINT(coin_selection, aps_create_tx_internal,
1480 wallet.GetName().c_str(),
1482 txr_grouped.has_value(),
1483 txr_grouped.has_value() ? txr_grouped->fee : 0,
1484 txr_grouped.has_value() && txr_grouped->change_pos.has_value() ? int32_t(*txr_grouped->change_pos) : -1);
1486 wallet.WalletLogPrintf(
"Fee non-grouped = %lld, grouped = %lld, using %s\n",
1487 txr_ungrouped.fee, txr_grouped->fee, use_aps ?
"grouped" :
"non-grouped");
1488 if (use_aps)
return txr_grouped;
1512 std::map<COutPoint, Coin> coins;
1516 wallet.chain().findCoins(coins);
1519 const auto& outPoint = txin.
prevout;
1521 if (!
wallet.IsMine(outPoint)) {
1522 if (coins[outPoint].
out.IsNull()) {
1523 return util::Error{
_(
"Unable to find UTXO for external input")};
1540 for (
const CTxIn& txin : res->tx->vin) {
std::shared_ptr< const CTransaction > CTransactionRef
void Shuffle(FastRandomContext &rng_fast)
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', call 'AutomaticCoinSelection' to select a set of coins such that nTargetValue - pre_set_inputs.total_amount is met.
Helper for findBlock to selectively return pieces of block data.
std::optional< CTxOut > GetExternalOutput(const COutPoint &outpoint) const
Returns the external output for the given outpoint if it exists.
COutPoint outpoint
The outpoint identifying this UTXO.
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.
bool m_avoid_partial_spends
Avoid partial use of funds sent to a given address.
FastRandomContext & rng_fast
Randomness to use in the context of coin selection.
util::Result< SelectionResult > KnapsackSolver(std::vector< OutputGroup > &groups, const CAmount &nTargetValue, CAmount change_target, FastRandomContext &rng, int max_selection_weight)
bool CachedTxIsTrusted(const CWallet &wallet, const CWalletTx &wtx, std::set< Txid > &trusted_parents)
void KeepDestination()
Keep the address. Do not return its key to the keypool when this object goes out of scope...
CAmount min_viable_change
Minimum amount for creating a change output.
mapValue_t mapValue
Key/value map with information about the transaction.
util::Result< CoinsResult > FetchSelectedInputs(const CWallet &wallet, const CCoinControl &coin_control, const CoinSelectionParams &coin_selection_params)
Fetch and validate coin control selected inputs.
std::optional< uint32_t > m_locktime
Locktime.
static constexpr size_t DUMMY_NESTED_P2WPKH_INPUT_SIZE
Pre-calculated constants for input size estimation in virtual size
std::map< OutputType, Groups > groups_by_type
static const int WITNESS_SCALE_FACTOR
Stores several 'Groups' whose were mapped by output type.
bool OutputIsChange(const CWallet &wallet, const CTxOut &txout)
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination corresponds to one with an address.
size_t Size() const
The following methods are provided so that CoinsResult can mimic a vector, i.e., methods can work wit...
int tx_noinputs_size
Size of the transaction before coin selection, consisting of the header and recipient output(s)...
static bool IsSegwit(const Descriptor &desc)
Whether the descriptor represents, directly or not, a witness program.
std::string StringForFeeReason(FeeReason reason)
is a home for simple string functions returning descriptive messages that are used in RPC and GUI int...
std::vector< COutput > All() const
Concatenate and return all COutputs as one vector.
std::optional< CAmount > total_effective_amount
Sum of all available coins effective value (each output value minus fees required to spend it) ...
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< unsigned char >> &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
CScriptWitness scriptWitness
Only serialized through CTransaction.
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
bool check_version_trucness
int64_t GetTime()
DEPRECATED, see GetTime.
static const uint32_t SEQUENCE_FINAL
Setting nSequence to this value for every input in a transaction disables nLockTime/IsFinalTx().
const CTxOut & FindNonChangeParentOutput(const CWallet &wallet, const COutPoint &outpoint)
Find non-change parent output.
virtual bool isInitialBlockDownload()=0
Check if in IBD.
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.
#define CHECK_NONFATAL(condition)
Identity function.
CAmount CalculateOutputValue(const TxType &tx)
CFeeRate GetDiscardRate(const CWallet &wallet)
Return the maximum feerate for discarding change.
void ApplyBumpFee(CAmount bump_fee)
util::Result< CTxDestination > GetReservedDestination(bool internal)
Reserve an address.
FlatSigningProvider m_external_provider
SigningProvider that has pubkeys and scripts to do spend size estimation for external inputs...
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost, unsigned int bytes_per_sigop)
Compute the virtual transaction size (weight reinterpreted as bytes).
uint32_t m_version
The version of the transaction we are trying to create.
static bool IsCurrentForAntiFeeSniping(interfaces::Chain &chain, const uint256 &block_hash)
std::optional< CAmount > GetAppropriateTotal(bool subtract_fee_outputs) const
static bool HasErrorMsg(const util::Result< SelectionResult > &res)
void AddProvider(std::unique_ptr< SigningProvider > provider)
consteval auto _(util::TranslatedLiteral str)
static int32_t GetTransactionWeight(const CTransaction &tx)
bool HasSelected() const
Returns true if there are pre-selected inputs.
bool CachedTxIsFromMe(const CWallet &wallet, const CWalletTx &wtx)
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible...
bilingual_str TransactionErrorString(const TransactionError err)
const std::vector< CTxIn > vin
util::Result< SelectionResult > CoinGrinder(std::vector< OutputGroup > &utxo_pool, const CAmount &selection_target, CAmount change_target, int max_selection_weight)
int64_t GetTxTime() const
int change_output_size
Size of a change output in bytes, determined by the output type.
std::map< OutputType, std::vector< COutput > > coins
int64_t CAmount
Amount in satoshis (Can be negative)
COutputs available for spending, stored by OutputType.
A transaction with a bunch of additional info that only the owner cares about.
bool include_immature_coinbase
void AddInputs(const OutputSet &inputs, bool subtract_fee_outputs)
uint32_t m_version
Version.
CFeeRate m_effective_feerate
The targeted feerate of the transaction being built.
CAmount total_amount
Sum of all available coins raw value.
static constexpr uint32_t MAX_BIP125_RBF_SEQUENCE
static decltype(CTransaction::version) constexpr TRUC_VERSION
CAmount m_min_change_target
Mininmum change to target in Knapsack solver and CoinGrinder: select coins to cover the payment and a...
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
static constexpr int64_t TRUC_CHILD_MAX_WEIGHT
std::vector< OutputGroup > positive_group
std::optional< Txid > truc_child_in_mempool
An input of a transaction.
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...
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).
int CalculateMaximumSignedInputSize(const CTxOut &txout, const COutPoint outpoint, const SigningProvider *provider, bool can_grind_r, const CCoinControl *coin_control)
static OutputType GetOutputType(TxoutType type, bool is_from_p2sh)
const std::vector< CTxOut > vout
uint64_t GetSerializeSize(const T &t)
bool IsDust(const CRecipient &recipient, const CFeeRate &dustRelayFee)
virtual bool findBlock(const uint256 &hash, const FoundBlock &block={})=0
Return whether node has the block and optionally return block metadata or contents.
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.
CAmount m_cost_of_change
Cost of creating the change output + cost of spending the change output in the future.
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
A signing provider to be used to interface with multiple signing providers at once.
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.
An output of a transaction.
A group of UTXOs paid to the same output script.
An outpoint - a combination of a transaction hash and an index n into its vout.
std::vector< CTxOut > vout
CAmount GetDustThreshold(const CTxOut &txout, const CFeeRate &dustRelayFeeIn)
virtual std::optional< int64_t > MaxSatisfactionElems() const =0
Get the maximum size number of stack elements for satisfying this descriptor.
#define Assume(val)
Assume is the identity function.
bool m_avoid_partial_spends
When true, always spend all (up to OUTPUT_GROUP_MAX_ENTRIES) or none of the outputs associated with t...
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...
Parameters for one iteration of Coin Selection.
bool m_avoid_address_reuse
Forbids inclusion of dirty (previously used) addresses.
util::Result< SelectionResult > SelectCoinsBnB(std::vector< OutputGroup > &utxo_pool, const CAmount &selection_target, const CAmount &cost_of_change, int max_selection_weight)
bool m_subtract_fee_outputs
Indicate that we are subtracting the fee from outputs.
static bool UseMaxSig(const std::optional< CTxIn > &txin, const CCoinControl *coin_control)
Whether to assume ECDSA signatures' will be high-r.
CFeeRate GetMinimumFeeRate(const CWallet &wallet, const CCoinControl &coin_control, FeeCalculation *feeCalc)
Estimate the minimum fee rate considering user set parameters and the required fee.
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...
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
static CTransactionRef MakeTransactionRef(Tx &&txIn)
uint64_t GetSerializeSizeForRecipient(const CRecipient &recipient)
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.
std::set< std::shared_ptr< COutput >, OutputPtrComparator > OutputSet
const int DEFAULT_MAX_DEPTH
Parameters for filtering which OutputGroups we may use in coin selection.
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)
std::optional< CAmount > GetEffectiveTotalAmount() const
bool m_include_unsafe_inputs
When true, allow unsafe coins to be selected during Coin Selection.
std::vector< OutputGroup > mixed_group
std::string FormatMoney(const CAmount n)
Money parsing/formatting utilities.
const int DEFAULT_MIN_DEPTH
static constexpr int32_t MAX_STANDARD_TX_WEIGHT
The maximum weight for transactions we're willing to relay/mine.
std::optional< int > m_max_tx_weight
The maximum weight for this transaction.
static constexpr size_t OUTPUT_GROUP_MAX_ENTRIES
#define EXCLUSIVE_LOCKS_REQUIRED(...)
int m_min_depth
Minimum chain depth value for coin availability.
An interface to be implemented by keystores that support signing.
void Erase(const std::unordered_set< COutPoint, SaltedOutpointHasher > &coins_to_remove)
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
Serialized script, used inside transaction inputs and outputs.
CreatedTransactionResult FundTransaction(CWallet &wallet, const CMutableTransaction &tx, const std::vector< CRecipient > &recipients, const UniValue &options, CCoinControl &coinControl, bool override_min_fee)
std::optional< int64_t > GetInputWeight(const COutPoint &outpoint) const
Returns the input weight.
static 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...
bool m_include_unsafe_inputs
If false, only safe inputs will be used.
#define TRACEPOINT(context,...)
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
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.
CoinsResult AvailableCoins(const CWallet &wallet, const CCoinControl *coinControl, std::optional< CFeeRate > feerate, const CoinFilterParams ¶ms)
Populate the CoinsResult struct with vectors of available COutputs, organized by OutputType.
bool m_allow_other_inputs
If true, the selection process can add extra unselected inputs from the wallet while requires all sel...
Use sat/vB fee rate unit.
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 ...
std::string GetAlgorithmName(const SelectionAlgorithm algo)
A wrapper to reserve an address from a wallet.
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac...
I randrange(I range) noexcept
Generate a random integer in the range [0..range), with range > 0.
static constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
TRACEPOINT_SEMAPHORE(coin_selection, selected_coins)
bilingual_str ErrorString(const Result< T > &result)
A reference to a CScript: the Hash160 of its serialization.
A mutable version of CTransaction.
bool IsExternalSelected(const COutPoint &outpoint) const
Returns true if the given output is selected as an external input.
static const uint32_t MAX_SEQUENCE_NONFINAL
This is the maximum sequence number that enables both nLockTime and OP_CHECKLOCKTIMEVERIFY (BIP 65)...
#define STR_INTERNAL_BUG(msg)
static const unsigned int LOCKTIME_THRESHOLD
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)
The basic transaction that is broadcasted on the network and contained in blocks. ...
void Add(OutputType type, const COutput &out)
int m_max_depth
Maximum chain depth value for coin availability.
virtual std::optional< OutputType > GetOutputType() const =0
is a home for public enum and struct type definitions that are used internally by node code...
CAmount GetTotalAmount() const
A UTXO under consideration for use in funding a new transaction.
bool IsSelected(const COutPoint &outpoint) const
Returns true if the given output is pre-selected.
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 ...
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.
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...
FilteredOutputGroups GroupOutputs(const CWallet &wallet, const CoinsResult &coins, const CoinSelectionParams &coin_sel_params, const std::vector< SelectionFilter > &filters, std::vector< OutputGroup > &ret_discarded_groups)
std::vector< COutPoint > ListSelected() const
List the selected inputs.
PreselectedInput & Select(const COutPoint &outpoint)
Lock-in the given output for spending.
CAmount m_change_fee
Cost of creating the change output.
Interface for parsed descriptor objects.
std::map< CTxDestination, std::vector< COutput > > ListCoins(const CWallet &wallet)
Return list of available coins and locked coins grouped by non-change output address.
#define Assert(val)
Identity function.
static const bool DEFAULT_WALLET_REJECT_LONG_CHAINS
Default for -walletrejectlongchains.
std::map< CoinEligibilityFilter, OutputGroupTypeMap > FilteredOutputGroups