From ad1eb77d50fbef697c99aa9add7fe6c4d165281c Mon Sep 17 00:00:00 2001 From: jeffro256 Date: Mon, 7 Apr 2025 14:48:44 -0500 Subject: [PATCH] carrot_impl: input_count_for_max_usable_money fix --- src/carrot_impl/input_selection.cpp | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/carrot_impl/input_selection.cpp b/src/carrot_impl/input_selection.cpp index 9f38ecd60..b6ae556a9 100644 --- a/src/carrot_impl/input_selection.cpp +++ b/src/carrot_impl/input_selection.cpp @@ -105,19 +105,19 @@ static void stable_sort_indices_by_block_index(const epee::span input_count_for_max_usable_money( const epee::span input_candidates, - const std::set selectable_inputs, - const std::map &required_money_by_input_count) + const std::set &selectable_inputs, + const std::map &fee_by_input_count) { // Returns (N, X) where the X is the sum of the amounts of the greatest N <= CARROT_MAX_TX_INPUTS - // inputs from selectable_inputs, maximizing X - R(N). R(N) is the required money for this - // transaction, including fee, for given input count N. This should correctly handle "almost-dust": - // inputs which are less than the fee, but greater than or equal to the difference of the fee - // compared to excluding that input. If this function returns N == 0, then there aren't enough - // usable funds, i.e. no N exists such that X - R(N) > 0. + // inputs from selectable_inputs, maximizing X - F(N). F(N) is the fee for this transaction, + // given input count N. This should correctly handle "almost-dust": inputs which are less than + // the fee, but greater than or equal to the difference of the fee compared to excluding that + // input. If this function returns N == 0, then there aren't enough usable funds, i.e. no N + // exists such that X - F(N) > 0. size_t num_ins = 0; boost::multiprecision::int128_t cumulative_input_sum = 0; - boost::multiprecision::int128_t last_required_money = 0; + rct::xmr_amount last_fee = 0; std::vector selectable_inputs_vec(selectable_inputs.cbegin(), selectable_inputs.cend()); stable_sort_indices_by_amount(input_candidates, selectable_inputs_vec); @@ -125,13 +125,14 @@ static std::pair input_count_for_max_us // for selectable indices in descending amount... for (auto it = selectable_inputs_vec.crbegin(); it != selectable_inputs_vec.crend(); ++it) { - ++num_ins; - if (num_ins > CARROT_MAX_TX_INPUTS) + if (num_ins == CARROT_MAX_TX_INPUTS) break; + ++num_ins; + const rct::xmr_amount amount = input_candidates[*it].core.amount; - if (amount < required_money_by_input_count.at(num_ins) - last_required_money) + if (amount < fee_by_input_count.at(num_ins) - last_fee) { // then this input doesn't pay for itself, rollback previous state and break // since all next inputs will have same amount or less @@ -140,6 +141,7 @@ static std::pair input_count_for_max_us } cumulative_input_sum += amount; + last_fee = fee_by_input_count.at(num_ins); } return {num_ins, cumulative_input_sum}; @@ -256,8 +258,9 @@ select_inputs_func_t make_single_transfer_input_selector( // Return early if not enough money in this selectable set... const auto max_usable_money = input_count_for_max_usable_money(input_candidates, selectable_indices, - required_money_by_input_count); - const bool enough_money = max_usable_money.first > 0; + fee_by_input_count); + const bool enough_money = max_usable_money.first > 0 + && max_usable_money.second >= required_money_by_input_count.at(max_usable_money.first); if (!enough_money) return;