@@ -17,6 +17,14 @@ namespace wallet {
1717static constexpr CAmount MIN_CHANGE{COIN / 100 };
1818// ! final minimum change amount after paying for fees
1919static const CAmount MIN_FINAL_CHANGE = MIN_CHANGE/2 ;
20+ // ! lower bound for randomly-chosen target change amount
21+ static constexpr CAmount CHANGE_LOWER{50000 };
22+ // ! upper bound for randomly-chosen target change amount
23+ static constexpr CAmount CHANGE_UPPER{1000000 };
24+ // Ensure that any randomly generated change targets are less than or equal to before.
25+ // Otherwise, tests may fail if funds are not enough to cover change.
26+ static_assert (CHANGE_UPPER <= MIN_CHANGE);
27+ static_assert (CHANGE_LOWER <= MIN_FINAL_CHANGE);
2028
2129/* * A UTXO under consideration for use in funding a new transaction. */
2230class COutput
@@ -99,6 +107,8 @@ struct CoinSelectionParams {
99107 CAmount m_min_change_target{MIN_CHANGE};
100108 /* * Cost of creating the change output. */
101109 CAmount m_change_fee{0 };
110+ /* * The pre-determined minimum value to target when funding a change output. */
111+ CAmount m_change_target{0 };
102112 /* * Cost of creating the change output + cost of spending the change output in the future. */
103113 CAmount m_cost_of_change{0 };
104114 /* * The targeted feerate of the transaction being built. */
@@ -223,6 +233,21 @@ struct OutputGroup
223233 */
224234[[nodiscard]] CAmount GetSelectionWaste (const std::set<COutput>& inputs, CAmount change_cost, CAmount target, bool use_effective_value = true );
225235
236+
237+ /* * Chooose a random change target for each transaction to make it harder to fingerprint the Core
238+ * wallet based on the change output values of transactions it creates.
239+ * The random value is between 50ksat and min(2 * payment_value, 1milsat)
240+ * When payment_value <= 25ksat, the value is just 50ksat.
241+ *
242+ * Making change amounts similar to the payment value may help disguise which output(s) are payments
243+ * are which ones are change. Using double the payment value may increase the number of inputs
244+ * needed (and thus be more expensive in fees), but breaks analysis techniques which assume the
245+ * coins selected are just sufficient to cover the payment amount ("unnecessary input" heuristic).
246+ *
247+ * @param[in] payment_value Average payment value of the transaction output(s).
248+ */
249+ [[nodiscard]] CAmount GenerateChangeTarget (CAmount payment_value, FastRandomContext& rng);
250+
226251struct SelectionResult
227252{
228253private:
0 commit comments