diff options
Diffstat (limited to 'src/wallet/spend.cpp')
-rw-r--r-- | src/wallet/spend.cpp | 21 |
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; |