@@ -17,6 +17,14 @@ namespace wallet {
17
17
static constexpr CAmount MIN_CHANGE{COIN / 100 };
18
18
// ! final minimum change amount after paying for fees
19
19
static 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);
20
28
21
29
/* * A UTXO under consideration for use in funding a new transaction. */
22
30
class COutput
@@ -99,6 +107,8 @@ struct CoinSelectionParams {
99
107
CAmount m_min_change_target{MIN_CHANGE};
100
108
/* * Cost of creating the change output. */
101
109
CAmount m_change_fee{0 };
110
+ /* * The pre-determined minimum value to target when funding a change output. */
111
+ CAmount m_change_target{0 };
102
112
/* * Cost of creating the change output + cost of spending the change output in the future. */
103
113
CAmount m_cost_of_change{0 };
104
114
/* * The targeted feerate of the transaction being built. */
@@ -223,6 +233,21 @@ struct OutputGroup
223
233
*/
224
234
[[nodiscard]] CAmount GetSelectionWaste (const std::set<COutput>& inputs, CAmount change_cost, CAmount target, bool use_effective_value = true );
225
235
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
+
226
251
struct SelectionResult
227
252
{
228
253
private:
0 commit comments