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.cpp21
1 files changed, 17 insertions, 4 deletions
diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp
index e0546c6210..1ad570442e 100644
--- a/src/wallet/spend.cpp
+++ b/src/wallet/spend.cpp
@@ -696,7 +696,12 @@ util::Result<SelectionResult> ChooseSelectionResult(interfaces::Chain& chain, co
};
// Maximum allowed weight for selected coins.
- int max_selection_weight = MAX_STANDARD_TX_WEIGHT - (coin_selection_params.tx_noinputs_size * WITNESS_SCALE_FACTOR);
+ int max_transaction_weight = coin_selection_params.m_max_tx_weight.value_or(MAX_STANDARD_TX_WEIGHT);
+ int tx_weight_no_input = coin_selection_params.tx_noinputs_size * WITNESS_SCALE_FACTOR;
+ int max_selection_weight = max_transaction_weight - tx_weight_no_input;
+ if (max_selection_weight <= 0) {
+ return util::Error{_("Maximum transaction weight is less than transaction weight without inputs")};
+ }
// SFFO frequently causes issues in the context of changeless input sets: skip BnB when SFFO is active
if (!coin_selection_params.m_subtract_fee_outputs) {
@@ -706,7 +711,11 @@ util::Result<SelectionResult> ChooseSelectionResult(interfaces::Chain& chain, co
}
// Deduct change weight because remaining Coin Selection algorithms can create change output
- max_selection_weight -= (coin_selection_params.change_output_size * WITNESS_SCALE_FACTOR);
+ int change_outputs_weight = coin_selection_params.change_output_size * WITNESS_SCALE_FACTOR;
+ max_selection_weight -= change_outputs_weight;
+ if (max_selection_weight < 0 && results.empty()) {
+ return util::Error{_("Maximum transaction weight is too low, can not accommodate change output")};
+ }
// The knapsack solver has some legacy behavior where it will spend dust outputs. We retain this behavior, so don't filter for positive only here.
if (auto knapsack_result{KnapsackSolver(groups.mixed_group, nTargetValue, coin_selection_params.m_min_change_target, coin_selection_params.rng_fast, max_selection_weight)}) {
@@ -801,7 +810,7 @@ util::Result<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& av
coin_selection_params.m_change_fee);
// Verify we haven't exceeded the maximum allowed weight
- int max_inputs_weight = MAX_STANDARD_TX_WEIGHT - (coin_selection_params.tx_noinputs_size * WITNESS_SCALE_FACTOR);
+ int max_inputs_weight = coin_selection_params.m_max_tx_weight.value_or(MAX_STANDARD_TX_WEIGHT) - (coin_selection_params.tx_noinputs_size * WITNESS_SCALE_FACTOR);
if (op_selection_result->GetWeight() > max_inputs_weight) {
return util::Error{_("The combination of the pre-selected inputs and the wallet automatic inputs selection exceeds the transaction maximum weight. "
"Please try sending a smaller amount or manually consolidating your wallet's UTXOs")};
@@ -1002,7 +1011,11 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
CoinSelectionParams coin_selection_params{rng_fast}; // Parameters for coin selection, init with dummy
coin_selection_params.m_avoid_partial_spends = coin_control.m_avoid_partial_spends;
coin_selection_params.m_include_unsafe_inputs = coin_control.m_include_unsafe_inputs;
-
+ coin_selection_params.m_max_tx_weight = coin_control.m_max_tx_weight.value_or(MAX_STANDARD_TX_WEIGHT);
+ int minimum_tx_weight = MIN_STANDARD_TX_NONWITNESS_SIZE * WITNESS_SCALE_FACTOR;
+ if (coin_selection_params.m_max_tx_weight.value() < minimum_tx_weight || coin_selection_params.m_max_tx_weight.value() > MAX_STANDARD_TX_WEIGHT) {
+ return util::Error{strprintf(_("Maximum transaction weight must be between %d and %d"), minimum_tx_weight, MAX_STANDARD_TX_WEIGHT)};
+ }
// Set the long term feerate estimate to the wallet's consolidate feerate
coin_selection_params.m_long_term_feerate = wallet.m_consolidate_feerate;