aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/spend.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet/spend.cpp')
-rw-r--r--src/wallet/spend.cpp46
1 files changed, 30 insertions, 16 deletions
diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp
index b51cd6332f..5d23ebd35a 100644
--- a/src/wallet/spend.cpp
+++ b/src/wallet/spend.cpp
@@ -709,6 +709,15 @@ util::Result<SelectionResult> ChooseSelectionResult(interfaces::Chain& chain, co
results.push_back(*knapsack_result);
} else append_error(knapsack_result);
+ if (coin_selection_params.m_effective_feerate > CFeeRate{3 * coin_selection_params.m_long_term_feerate}) { // Minimize input set for feerates of at least 3×LTFRE (default: 30 ṩ/vB+)
+ if (auto cg_result{CoinGrinder(groups.positive_group, nTargetValue, coin_selection_params.m_min_change_target, max_inputs_weight)}) {
+ cg_result->ComputeAndSetWaste(coin_selection_params.min_viable_change, coin_selection_params.m_cost_of_change, coin_selection_params.m_change_fee);
+ results.push_back(*cg_result);
+ } else {
+ append_error(cg_result);
+ }
+ }
+
if (auto srd_result{SelectCoinsSRD(groups.positive_group, nTargetValue, coin_selection_params.m_change_fee, coin_selection_params.rng_fast, max_inputs_weight)}) {
results.push_back(*srd_result);
} else append_error(srd_result);
@@ -1127,7 +1136,12 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
return util::Error{err.empty() ?_("Insufficient funds") : err};
}
const SelectionResult& result = *select_coins_res;
- TRACE5(coin_selection, selected_coins, wallet.GetName().c_str(), GetAlgorithmName(result.GetAlgo()).c_str(), result.GetTarget(), result.GetWaste(), result.GetSelectedValue());
+ TRACE5(coin_selection, selected_coins,
+ wallet.GetName().c_str(),
+ GetAlgorithmName(result.GetAlgo()).c_str(),
+ result.GetTarget(),
+ result.GetWaste(),
+ result.GetSelectedValue());
const CAmount change_amount = result.GetChange(coin_selection_params.min_viable_change, coin_selection_params.m_change_fee);
if (change_amount > 0) {
@@ -1336,8 +1350,11 @@ util::Result<CreatedTransactionResult> CreateTransaction(
LOCK(wallet.cs_wallet);
auto res = CreateTransactionInternal(wallet, vecSend, change_pos, coin_control, sign);
- TRACE4(coin_selection, normal_create_tx_internal, wallet.GetName().c_str(), bool(res),
- res ? res->fee : 0, res && res->change_pos.has_value() ? *res->change_pos : 0);
+ TRACE4(coin_selection, normal_create_tx_internal,
+ wallet.GetName().c_str(),
+ bool(res),
+ res ? res->fee : 0,
+ res && res->change_pos.has_value() ? int32_t(*res->change_pos) : -1);
if (!res) return res;
const auto& txr_ungrouped = *res;
// try with avoidpartialspends unless it's enabled already
@@ -1354,8 +1371,12 @@ util::Result<CreatedTransactionResult> CreateTransaction(
auto txr_grouped = CreateTransactionInternal(wallet, vecSend, change_pos, tmp_cc, sign);
// if fee of this alternative one is within the range of the max fee, we use this one
const bool use_aps{txr_grouped.has_value() ? (txr_grouped->fee <= txr_ungrouped.fee + wallet.m_max_aps_fee) : false};
- TRACE5(coin_selection, aps_create_tx_internal, wallet.GetName().c_str(), use_aps, txr_grouped.has_value(),
- txr_grouped.has_value() ? txr_grouped->fee : 0, txr_grouped.has_value() && txr_grouped->change_pos.has_value() ? *txr_grouped->change_pos : 0);
+ TRACE5(coin_selection, aps_create_tx_internal,
+ wallet.GetName().c_str(),
+ use_aps,
+ txr_grouped.has_value(),
+ txr_grouped.has_value() ? txr_grouped->fee : 0,
+ txr_grouped.has_value() && txr_grouped->change_pos.has_value() ? int32_t(*txr_grouped->change_pos) : -1);
if (txr_grouped) {
wallet.WalletLogPrintf("Fee non-grouped = %lld, grouped = %lld, using %s\n",
txr_ungrouped.fee, txr_grouped->fee, use_aps ? "grouped" : "non-grouped");
@@ -1365,18 +1386,11 @@ util::Result<CreatedTransactionResult> CreateTransaction(
return res;
}
-util::Result<CreatedTransactionResult> FundTransaction(CWallet& wallet, const CMutableTransaction& tx, std::optional<unsigned int> change_pos, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl coinControl)
+util::Result<CreatedTransactionResult> FundTransaction(CWallet& wallet, const CMutableTransaction& tx, const std::vector<CRecipient>& vecSend, std::optional<unsigned int> change_pos, bool lockUnspents, CCoinControl coinControl)
{
- std::vector<CRecipient> vecSend;
-
- // Turn the txout set into a CRecipient vector.
- for (size_t idx = 0; idx < tx.vout.size(); idx++) {
- const CTxOut& txOut = tx.vout[idx];
- CTxDestination dest;
- ExtractDestination(txOut.scriptPubKey, dest);
- CRecipient recipient = {dest, txOut.nValue, setSubtractFeeFromOutputs.count(idx) == 1};
- vecSend.push_back(recipient);
- }
+ // We want to make sure tx.vout is not used now that we are passing outputs as a vector of recipients.
+ // This sets us up to remove tx completely in a future PR in favor of passing the inputs directly.
+ assert(tx.vout.empty());
// Set the user desired locktime
coinControl.m_locktime = tx.nLockTime;