fixup! Remove coins that harm anonymity
MODIFY
WalletWasabi/WabiSabi/Client/CoinJoinClient.cs
WalletWasabi/WabiSabi/Client/CoinJoinClient.cs
@@ -26,6 +26,7 @@ namespace WalletWasabi.WabiSabi.Client;
public class CoinJoinClient
{
private const int MaxInputsRegistrableByWallet = 10; // how many
+ private const int MaxWeightedAnonLoss = 3;
private static readonly Money MinimumOutputAmountSanity = Money.Coins(0.0001m); // ignore rounds with too big minimum denominations
private static readonly TimeSpan ExtraPhaseTimeoutMargin = TimeSpan.FromMinutes(1);
@@ -812,28 +813,26 @@ public class CoinJoinClient
}
}
- double winnerCost = 0;
- while ((winner.Sum(x => x.Amount) > liquidityClue) && (winnerCost/winner.Sum(x => x.Amount) < 3))
+ double winnerAnonLoss = GetAnonLoss(winner);
+ while ((winner.Sum(x => x.Amount) > liquidityClue) && (winnerAnonLoss > MaxWeightedAnonLoss))
{
List<SmartCoin> bestReducedWinner = winner;
- var minimumAnonScore = bestReducedWinner.Min(x => x.HdPubKey.AnonymitySet);
- var minCost = bestReducedWinner.Sum(x => (x.HdPubKey.AnonymitySet - minimumAnonScore) * x.Amount.Satoshi);
+ var bestAnonLoss = winnerAnonLoss;
foreach (SmartCoin coin in winner.Except(new[] { selectedNonPrivateCoin }))
{
var reducedWinner = winner.Except(new[] { coin });
- minimumAnonScore = reducedWinner.Min(x => x.HdPubKey.AnonymitySet);
- var cost = reducedWinner.Sum(x => (x.HdPubKey.AnonymitySet - minimumAnonScore) * x.Amount.Satoshi);
+ var anonLoss = GetAnonLoss(reducedWinner);
- if (cost < minCost)
+ if (anonLoss <= bestAnonLoss)
{
- minCost = cost;
+ bestAnonLoss = anonLoss;
bestReducedWinner = reducedWinner.ToList();
}
}
winner = bestReducedWinner;
- winnerCost = minCost;
+ winnerAnonLoss = bestAnonLoss;
}
if (winner.Count != finalCandidate.Count())
@@ -846,6 +845,12 @@ public class CoinJoinClient
return winner.ToShuffled()?.ToImmutableList() ?? ImmutableList<SmartCoin>.Empty;
}
+ private static double GetAnonLoss(IEnumerable<SmartCoin> coins)
+ {
+ double minimumAnonScore = coins.Min(x => x.HdPubKey.AnonymitySet);
+ return coins.Sum(x => (x.HdPubKey.AnonymitySet - minimumAnonScore) * x.Amount.Satoshi) / coins.Sum(x => x.Amount.Satoshi);
+ }
+
private static int GetRandomBiasedSameTxAllowance(WasabiRandom rnd, int percent)
{
for (int num = 0; num <= 100; num++)

fixup! Remove coins that harm anonymity