Repository: bitcoin/bitcoin
File: src/wallet/coinselection.h (C/C++)

Code before:
    CAmount m_cost_of_change{0};
    /** The targeted feerate of the transaction being built. */
    CFeeRate m_effective_feerate;
    /** The feerate estimate used to estimate an upper bound on what should be sufficient to spend
     * the change output sometime in the future. */
    CFeeRate m_long_term_feerate;
    /** If the cost to spend a change output at the discard feerate exceeds its value, drop it to fees. */
    CFeeRate m_discard_feerate;
    /** Size of the transaction before coin selection, consisting of the header and recipient
     * output(s), excluding the inputs and change output(s). */
    int64_t tx_noinputs_size = 0;
    /** Indicate that we are subtracting the fee from outputs */
    bool m_subtract_fee_outputs = false;
    /** When true, always spend all (up to OUTPUT_GROUP_MAX_ENTRIES) or none of the outputs
     * associated with the same address. This helps reduce privacy leaks resulting from address
     * reuse. Dust outputs are not eligible to be added to output groups and thus not considered. */
    bool m_avoid_partial_spends = false;
    /**
     * When true, allow unsafe coins to be selected during Coin Selection. This may spend unconfirmed outputs:
     * 1) Received from other wallets, 2) replacing other txs, 3) that have been replaced.
     */
    bool m_include_unsafe_inputs = false;
    /**
     * The maximally sized transaction we are willing to make.
     */
    std::optional<int64_t> m_max_tx_weight{std::nullopt};

    CoinSelectionParams(FastRandomContext& rng_fast, int change_output_size, size_t change_spend_size,
                        CAmount min_change_target, CFeeRate effective_feerate,
                        CFeeRate long_term_feerate, CFeeRate discard_feerate, int tx_noinputs_size, bool avoid_partial,
                        std::optional<int64_t> max_tx_weight = std::nullopt)
        : rng_fast{rng_fast},
          change_output_size(change_output_size),
          change_spend_size(change_spend_size),
          m_min_change_target(min_change_target),
          m_effective_feerate(effective_feerate),
          m_long_term_feerate(long_term_feerate),
          m_discard_feerate(discard_feerate),
          tx_noinputs_size(tx_noinputs_size),
          m_avoid_partial_spends(avoid_partial),
          m_max_tx_weight(max_tx_weight)
    {
    }
    CoinSelectionParams(FastRandomContext& rng_fast)
        : rng_fast{rng_fast} {}
};

/** Parameters for filtering which OutputGroups we may use in coin selection.
 * We start by being very selective and requiring multiple confirmations and
 * then get more permissive if we cannot fund the transaction. */
struct CoinEligibilityFilter

Review comment (suggestion):
In "[wallet, rpc]: add `max_tx_weight` to tx funding options" (854acd72e99dc9f0924c5f0b5b7a657b39538911):

I’m a bit surprised by this sudden type change in a commit whose commit message doesn’t mention it. While I agree in principal that `size_t` is an inappropriate type for variables storing `vsize` or `weight`, could you please explain your motivation to change the types, and especially in this context? If you are retyping unrelated variables, I think that should perhaps  be a separate commit. If you are changing the types of `change_output_size` and `tx_noinputs_size`, why not also `change_spend_size`?
Perhaps if we are getting big into the business of changing the types of various transaction size, vsize and weight variables, we should perhaps consider introducing explicit types for weight, size, and vsize to prevent people accidentally mistaking them for the same type. On the other hand, that feels like the sort of change that will never propagate to the entire codebase, so I’m not sure it’s a good idea to even start.

Code after:
    CAmount m_cost_of_change{0};
    /** The targeted feerate of the transaction being built. */
    CFeeRate m_effective_feerate;
    /** The feerate estimate used to estimate an upper bound on what should be sufficient to spend
     * the change output sometime in the future. */
    CFeeRate m_long_term_feerate;
    /** If the cost to spend a change output at the discard feerate exceeds its value, drop it to fees. */
    CFeeRate m_discard_feerate;
    /** Size of the transaction before coin selection, consisting of the header and recipient
     * output(s), excluding the inputs and change output(s). */
    int tx_noinputs_size = 0;
    /** Indicate that we are subtracting the fee from outputs */
    bool m_subtract_fee_outputs = false;
    /** When true, always spend all (up to OUTPUT_GROUP_MAX_ENTRIES) or none of the outputs
     * associated with the same address. This helps reduce privacy leaks resulting from address
     * reuse. Dust outputs are not eligible to be added to output groups and thus not considered. */
    bool m_avoid_partial_spends = false;
    /**
     * When true, allow unsafe coins to be selected during Coin Selection. This may spend unconfirmed outputs:
     * 1) Received from other wallets, 2) replacing other txs, 3) that have been replaced.
     */
    bool m_include_unsafe_inputs = false;
    /** The maximum weight for this transaction. */
    std::optional<int> m_max_tx_weight{std::nullopt};

    CoinSelectionParams(FastRandomContext& rng_fast, int change_output_size, int change_spend_size,
                        CAmount min_change_target, CFeeRate effective_feerate,
                        CFeeRate long_term_feerate, CFeeRate discard_feerate, int tx_noinputs_size, bool avoid_partial,
                        std::optional<int> max_tx_weight = std::nullopt)
        : rng_fast{rng_fast},
          change_output_size(change_output_size),
          change_spend_size(change_spend_size),
          m_min_change_target(min_change_target),
          m_effective_feerate(effective_feerate),
          m_long_term_feerate(long_term_feerate),
          m_discard_feerate(discard_feerate),
          tx_noinputs_size(tx_noinputs_size),
          m_avoid_partial_spends(avoid_partial),
          m_max_tx_weight(max_tx_weight)
    {
    }
    CoinSelectionParams(FastRandomContext& rng_fast)
        : rng_fast{rng_fast} {}
};

/** Parameters for filtering which OutputGroups we may use in coin selection.
 * We start by being very selective and requiring multiple confirmations and
 * then get more permissive if we cannot fund the transaction. */
struct CoinEligibilityFilter
{
    /** Minimum number of confirmations for outputs that we sent to ourselves.