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.tx->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.
tx->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};
381 if (nDepth == 0 && wtx.
mapValue.contains(
"replaces_txid")) {
393 if (nDepth == 0 && wtx.
mapValue.contains(
"replaced_by_txid")) {
404 size_t ancestors, unused_cluster_count;
405 wallet.chain().getTransactionAncestry(wtx.
tx->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.
tx->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->
tx->vout.size() <= prevout.
n ||
535 !
wallet.IsMine(it->
tx->vout[prevout.
n])) {
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);
675 if (!accepted) ret_discarded_groups.emplace_back(
group);
680 push_output_groups(spk_to_groups_map,
false);
681 push_output_groups(spk_to_positive_groups_map,
true);
683 return filtered_groups;
689 const std::vector<SelectionFilter>& filters)
691 std::vector<OutputGroup> unused;
702 std::vector<SelectionResult> results;
708 if (result) results.push_back(*result);
712 if (results.size() > 0)
return *std::min_element(results.begin(), results.end());
717 if (allow_mixed_output_types && groups.
TypesCount() > 1) {
728 std::vector<SelectionResult> results;
729 std::vector<util::Result<SelectionResult>> errors;
734 errors.emplace_back(std::move(result));
741 int max_selection_weight = max_transaction_weight - tx_weight_no_input;
742 if (max_selection_weight <= 0) {
743 return util::Error{
_(
"Maximum transaction weight is less than transaction weight without inputs")};
749 results.push_back(*bnb_result);
750 }
else append_error(std::move(bnb_result));
755 max_selection_weight -= change_outputs_weight;
756 if (max_selection_weight < 0 && results.empty()) {
757 return util::Error{
_(
"Maximum transaction weight is too low, can not accommodate change output")};
762 results.push_back(*knapsack_result);
763 }
else append_error(std::move(knapsack_result));
768 results.push_back(*cg_result);
770 append_error(std::move(cg_result));
775 results.push_back(*srd_result);
776 }
else append_error(std::move(srd_result));
778 if (results.empty()) {
781 return errors.empty() ?
util::Error() : std::move(errors.front());
785 for (
auto& result : results) {
786 std::vector<COutPoint> outpoints;
789 for (
auto& coin : coins) {
790 if (coin->depth > 0)
continue;
791 outpoints.push_back(coin->outpoint);
792 summed_bump_fees += coin->ancestor_bump_fees;
795 if (!combined_bump_fee.has_value()) {
796 return util::Error{
_(
"Failed to calculate bump fees, because unconfirmed UTXOs depend on an enormous cluster of unconfirmed transactions.")};
798 CAmount bump_fee_overestimate = summed_bump_fees - combined_bump_fee.value();
799 if (bump_fee_overestimate) {
800 result.SetBumpFeeDiscount(bump_fee_overestimate);
807 return *std::min_element(results.begin(), results.end());
819 return util::Error{
_(
"The preselected coins total amount does not cover the transaction target. "
820 "Please allow other inputs to be automatically selected or include more coins manually")};
824 for (
const auto& output: pre_set_inputs.
All()) {
825 preset_coin_set.insert(std::make_shared<COutput>(output));
829 if (selection_target <= 0) {
839 if (selection_target > available_coins_total_amount) {
845 if (!op_selection_result)
return op_selection_result;
848 if (!pre_set_inputs.
coins.empty()) {
850 assert(preset_total.has_value());
851 SelectionResult preselected(preset_total.value(), SelectionAlgorithm::MANUAL);
853 op_selection_result->Merge(preselected);
860 if (op_selection_result->GetWeight() > max_inputs_weight) {
861 return util::Error{
_(
"The combination of the pre-selected inputs and the wallet automatic inputs selection exceeds the transaction maximum weight. "
862 "Please try sending a smaller amount or manually consolidating your wallet's UTXOs")};
865 return op_selection_result;
875 unsigned int limit_ancestor_count = 0;
876 unsigned int limit_descendant_count = 0;
877 wallet.chain().getPackageLimits(limit_ancestor_count, limit_descendant_count);
878 const size_t max_ancestors = (size_t)std::max<int64_t>(1, limit_ancestor_count);
879 const size_t max_cluster_count = (size_t)std::max<int64_t>(1, limit_descendant_count);
894 std::vector<SelectionFilter> ordered_filters{
902 if (
wallet.m_spend_zero_conf_change) {
904 ordered_filters.push_back({
CoinEligibilityFilter(0, 1, std::min(
size_t{4}, max_ancestors/3), std::min(
size_t{4}, max_cluster_count/3))});
909 ordered_filters.push_back({
CoinEligibilityFilter(0, 1, max_ancestors-1, max_cluster_count-1,
true)});
913 ordered_filters.push_back({
CoinEligibilityFilter(0, 0, max_ancestors-1, max_cluster_count-1,
true)});
919 if (!fRejectLongChains) {
921 std::numeric_limits<uint64_t>::max(),
927 std::vector<OutputGroup> discarded_groups;
932 CAmount total_unconf_long_chain = 0;
933 for (
const auto&
group : discarded_groups) {
934 total_discarded +=
group.GetSelectionAmount();
935 if (
group.m_ancestors >= max_ancestors ||
group.m_max_cluster_count >= max_cluster_count) total_unconf_long_chain +=
group.GetSelectionAmount();
938 if (
CAmount total_amount = available_coins.
GetTotalAmount() - total_discarded; total_amount < value_to_select) {
940 if (total_amount + total_unconf_long_chain > value_to_select) {
941 return util::Error{
_(
"Unconfirmed UTXOs are available, but spending them creates a chain of transactions that will be rejected by the mempool")};
949 std::vector<util::Result<SelectionResult>> res_detailed_errors;
951 for (
const auto& select_filter : ordered_filters) {
952 auto it = filtered_groups.find(select_filter.filter);
953 if (it == filtered_groups.end())
continue;
954 if (updated_selection_params.
m_version ==
TRUC_VERSION && (select_filter.filter.conf_mine == 0 || select_filter.filter.conf_theirs == 0)) {
960 updated_selection_params, select_filter.allow_mixed_output_types)}) {
966 if (
HasErrorMsg(res)) res_detailed_errors.emplace_back(std::move(res));
971 if (!res_detailed_errors.empty())
return std::move(res_detailed_errors.front());
984 constexpr int64_t MAX_ANTI_FEE_SNIPING_TIP_AGE = 8 * 60 * 60;
987 if (block_time < (
GetTime() - MAX_ANTI_FEE_SNIPING_TIP_AGE)) {
1037 for (
const auto& in : tx.
vin) {
1061 const std::vector<CRecipient>& vecSend,
1062 std::optional<unsigned int> change_pos,
1071 txNew.
version = coin_control.m_version;
1074 coin_selection_params.m_avoid_partial_spends = coin_control.m_avoid_partial_spends;
1075 coin_selection_params.m_include_unsafe_inputs = coin_control.m_include_unsafe_inputs;
1077 coin_selection_params.m_version = coin_control.m_version;
1079 if (coin_selection_params.m_max_tx_weight.value() < minimum_tx_weight || coin_selection_params.m_max_tx_weight.value() >
MAX_STANDARD_TX_WEIGHT) {
1083 coin_selection_params.m_long_term_feerate =
wallet.m_consolidate_feerate;
1088 const OutputType change_type =
wallet.TransactionChangeType(coin_control.m_change_type ? *coin_control.m_change_type :
wallet.m_default_change_type, vecSend);
1090 unsigned int outputs_to_subtract_fee_from = 0;
1091 for (
const auto& recipient : vecSend) {
1092 if (
IsDust(recipient,
wallet.chain().relayDustFee())) {
1098 recipients_sum += recipient.nAmount;
1100 if (recipient.fSubtractFeeFromAmount) {
1101 outputs_to_subtract_fee_from++;
1102 coin_selection_params.m_subtract_fee_outputs =
true;
1111 if (!std::get_if<CNoDestination>(&coin_control.destChange)) {
1136 CTxOut change_prototype_txout(0, scriptChange);
1137 coin_selection_params.change_output_size =
GetSerializeSize(change_prototype_txout);
1143 if (change_spend_size == -1) {
1146 coin_selection_params.change_spend_size = change_spend_size;
1157 if (coin_control.m_feerate && coin_selection_params.m_effective_feerate > *coin_control.m_feerate) {
1159 auto msg{
strprintf(
_(
"Fee rate (%s) is lower than the minimum fee rate setting (%s)."),
1160 coin_control.m_feerate->ToString(feerate_format),
1161 coin_selection_params.m_effective_feerate.ToString(feerate_format))};
1163 msg +=
strprintf(
_(
"\nConsider modifying %s (%s) or %s (%s)."),
1165 wallet.m_min_fee.ToString(feerate_format),
1167 wallet.chain().relayMinFee().ToString(feerate_format));
1173 return util::Error{
strprintf(
_(
"Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable %s."),
"-fallbackfee")};
1181 coin_selection_params.m_change_fee = coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.change_output_size);
1182 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;
1184 coin_selection_params.m_min_change_target =
GenerateChangeTarget(std::floor(recipients_sum / vecSend.size()), coin_selection_params.m_change_fee, rng_fast);
1189 const auto dust =
GetDustThreshold(change_prototype_txout, coin_selection_params.m_discard_feerate);
1190 const auto change_spend_fee = coin_selection_params.m_discard_feerate.GetFee(coin_selection_params.change_spend_size);
1191 coin_selection_params.min_viable_change = std::max(change_spend_fee + 1, dust);
1194 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);
1195 CAmount selection_target = recipients_sum + not_input_fees;
1199 if (selection_target == 0 && !coin_control.HasSelected()) {
1200 return util::Error{
_(
"Transaction requires one destination of non-zero value, a non-zero feerate, or a pre-selected input")};
1205 if (coin_control.HasSelected()) {
1208 preset_inputs = *res_fetch_inputs;
1214 if (coin_control.m_allow_other_inputs) {
1215 available_coins =
AvailableCoins(
wallet, &coin_control, coin_selection_params.m_effective_feerate);
1219 auto select_coins_res =
SelectCoins(
wallet, available_coins, preset_inputs, selection_target, coin_control, coin_selection_params);
1220 if (!select_coins_res) {
1229 if (available_balance >= recipients_sum) {
1234 if (available_effective_balance < selection_target) {
1235 Assume(!coin_selection_params.m_subtract_fee_outputs);
1236 return util::Error{
strprintf(
_(
"The total exceeds your balance when the %s transaction fee is included."),
FormatMoney(selection_target - recipients_sum))};
1245 wallet.GetName().c_str(),
1252 txNew.
vout.reserve(vecSend.size() + 1);
1253 for (
const auto& recipient : vecSend)
1257 const CAmount change_amount = result.
GetChange(coin_selection_params.min_viable_change, coin_selection_params.m_change_fee);
1258 if (change_amount > 0) {
1259 CTxOut newTxOut(change_amount, scriptChange);
1263 }
else if ((
unsigned int)*change_pos > txNew.
vout.size()) {
1264 return util::Error{
_(
"Transaction change output index out of range")};
1266 txNew.
vout.insert(txNew.
vout.begin() + *change_pos, newTxOut);
1268 change_pos = std::nullopt;
1274 if (coin_control.HasSelected() && coin_control.HasSelectedOrder()) {
1279 std::stable_sort(selected_coins.begin(), selected_coins.end(),
1280 [&coin_control](
const std::shared_ptr<COutput>& a,
const std::shared_ptr<COutput>& b) {
1281 auto a_pos = coin_control.GetSelectionPos(a->outpoint);
1282 auto b_pos = coin_control.GetSelectionPos(b->outpoint);
1283 if (a_pos.has_value() && b_pos.has_value()) {
1284 return a_pos.value() < b_pos.value();
1285 }
else if (a_pos.has_value() && !b_pos.has_value()) {
1301 bool use_anti_fee_sniping =
true;
1303 txNew.vin.reserve(selected_coins.size());
1304 for (
const auto& coin : selected_coins) {
1305 std::optional<uint32_t>
sequence = coin_control.GetSequence(coin->outpoint);
1308 use_anti_fee_sniping =
false;
1310 txNew.vin.emplace_back(coin->outpoint,
CScript{},
sequence.value_or(default_sequence));
1312 auto scripts = coin_control.GetScripts(coin->outpoint);
1313 if (scripts.first) {
1314 txNew.vin.back().scriptSig = *scripts.first;
1316 if (scripts.second) {
1317 txNew.vin.back().scriptWitness = *scripts.second;
1320 if (coin_control.m_locktime) {
1321 txNew.nLockTime = coin_control.m_locktime.value();
1323 use_anti_fee_sniping =
false;
1325 if (use_anti_fee_sniping) {
1331 int nBytes = tx_sizes.vsize;
1333 return util::Error{
_(
"Missing solving data for estimating transaction size")};
1335 CAmount fee_needed = coin_selection_params.m_effective_feerate.GetFee(nBytes) + result.GetTotalBumpFees();
1337 Assume(recipients_sum + change_amount == output_value);
1338 CAmount current_fee = result.GetSelectedValue() - output_value;
1341 if (current_fee < 0) {
1346 if (change_pos && fee_needed < current_fee) {
1347 auto& change = txNew.vout.at(*change_pos);
1348 change.nValue += current_fee - fee_needed;
1350 if (fee_needed != current_fee) {
1356 if (coin_selection_params.m_subtract_fee_outputs) {
1357 CAmount to_reduce = fee_needed - current_fee;
1360 for (
const auto& recipient : vecSend)
1362 if (change_pos && i == *change_pos) {
1365 CTxOut& txout = txNew.vout[i];
1367 if (recipient.fSubtractFeeFromAmount)
1369 txout.
nValue -= to_reduce / outputs_to_subtract_fee_from;
1374 txout.
nValue -= to_reduce % outputs_to_subtract_fee_from;
1380 return util::Error{
_(
"The transaction amount is too small to pay the fee")};
1382 return util::Error{
_(
"The transaction amount is too small to send after the fee has been deducted")};
1389 if (fee_needed != current_fee) {
1396 if (fee_needed > current_fee) {
1401 if (scriptChange.empty() && change_pos) {
1405 if (
sign && !
wallet.SignTransaction(txNew)) {
1419 if (current_fee >
wallet.m_default_max_tx_fee) {
1425 auto result =
wallet.chain().checkChainLimits(tx);
1433 reservedest.KeepDestination();
1435 wallet.WalletLogPrintf(
"Coin Selection: Algorithm:%s, Waste Metric Score:%d\n",
GetAlgorithmName(result.GetAlgo()), result.GetWaste());
1436 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",
1437 current_fee, nBytes, feeCalc.returnedTarget, feeCalc.desiredTarget,
StringForFeeReason(feeCalc.reason), feeCalc.est.decay,
1438 feeCalc.est.pass.start, feeCalc.est.pass.end,
1439 (feeCalc.est.pass.totalConfirmed + feeCalc.est.pass.inMempool + feeCalc.est.pass.leftMempool) > 0.0 ? 100 * feeCalc.est.pass.withinTarget / (feeCalc.est.pass.totalConfirmed + feeCalc.est.pass.inMempool + feeCalc.est.pass.leftMempool) : 0.0,
1440 feeCalc.est.pass.withinTarget, feeCalc.est.pass.totalConfirmed, feeCalc.est.pass.inMempool, feeCalc.est.pass.leftMempool,
1441 feeCalc.est.fail.start, feeCalc.est.fail.end,
1442 (feeCalc.est.fail.totalConfirmed + feeCalc.est.fail.inMempool + feeCalc.est.fail.leftMempool) > 0.0 ? 100 * feeCalc.est.fail.withinTarget / (feeCalc.est.fail.totalConfirmed + feeCalc.est.fail.inMempool + feeCalc.est.fail.leftMempool) : 0.0,
1443 feeCalc.est.fail.withinTarget, feeCalc.est.fail.totalConfirmed, feeCalc.est.fail.inMempool, feeCalc.est.fail.leftMempool);
1444 return CreatedTransactionResult(tx, current_fee, change_pos, feeCalc);
1449 const std::vector<CRecipient>& vecSend,
1450 std::optional<unsigned int> change_pos,
1454 if (vecSend.empty()) {
1455 return util::Error{
_(
"Transaction must have at least one recipient")};
1458 if (std::any_of(vecSend.cbegin(), vecSend.cend(), [](
const auto& recipient){ return recipient.nAmount < 0; })) {
1459 return util::Error{
_(
"Transaction amounts must not be negative")};
1465 TRACEPOINT(coin_selection, normal_create_tx_internal,
1466 wallet.GetName().c_str(),
1469 res && res->change_pos.has_value() ? int32_t(*res->change_pos) : -1);
1470 if (!res)
return res;
1471 const auto& txr_ungrouped = *res;
1474 TRACEPOINT(coin_selection, attempting_aps_create_tx,
wallet.GetName().c_str());
1479 if (txr_ungrouped.change_pos) {
1485 const bool use_aps{txr_grouped.has_value() ? (txr_grouped->fee <= txr_ungrouped.fee +
wallet.m_max_aps_fee) :
false};
1486 TRACEPOINT(coin_selection, aps_create_tx_internal,
1487 wallet.GetName().c_str(),
1489 txr_grouped.has_value(),
1490 txr_grouped.has_value() ? txr_grouped->fee : 0,
1491 txr_grouped.has_value() && txr_grouped->change_pos.has_value() ? int32_t(*txr_grouped->change_pos) : -1);
1493 wallet.WalletLogPrintf(
"Fee non-grouped = %lld, grouped = %lld, using %s\n",
1494 txr_ungrouped.fee, txr_grouped->fee, use_aps ?
"grouped" :
"non-grouped");
1495 if (use_aps)
return txr_grouped;
1519 std::map<COutPoint, Coin> coins;
1523 wallet.chain().findCoins(coins);
1526 const auto& outPoint = txin.
prevout;
1528 if (!
wallet.IsMine(outPoint)) {
1529 if (coins[outPoint].
out.IsNull()) {
1530 return util::Error{
_(
"Unable to find UTXO for external input")};
1547 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.
static 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 const uint32_t MAX_SEQUENCE_NONFINAL
This is the maximum sequence number that enables both nLockTime and OP_CHECKLOCKTIMEVERIFY (BIP 65).
static const uint32_t SEQUENCE_FINAL
Setting nSequence to this value for every input in a transaction disables nLockTime/IsFinalTx().
CScriptWitness scriptWitness
Only serialized through CTransaction.
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.
mapValue_t mapValue
Key/value map with information about the transaction.
std::optional< Txid > truc_child_in_mempool
int64_t GetTxTime() 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)
static const 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)
static 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)
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)
const int DEFAULT_MIN_DEPTH
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)
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.
const int DEFAULT_MAX_DEPTH
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',...
CFeeRate GetMinimumFeeRate(const CWallet &wallet, const CCoinControl &coin_control, FeeCalculation *feeCalc)
Estimate the minimum fee rate considering user set parameters and the required fee.
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)
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.
static const bool DEFAULT_WALLET_REJECT_LONG_CHAINS
Default for -walletrejectlongchains.
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).
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
static 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.
static const 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.
static constexpr decltype(CTransaction::version) TRUC_VERSION
static constexpr int64_t TRUC_CHILD_MAX_WEIGHT
static 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)