different concept: check if winners are on reused addresses and add the coins
MODIFY
WalletWasabi/WabiSabi/Client/CoinJoinClient.cs
WalletWasabi/WabiSabi/Client/CoinJoinClient.cs
@@ -667,20 +667,6 @@ public class CoinJoinClient
return ImmutableList<TCoin>.Empty;
}
- var sameAddressCoins = semiPrivateCoins
- .Union(redCoins)
- .GroupBy(x => x.HdPubKey)
- .Select(x => x.ToList())
- .Where(x => x.Count > 1)
- .OrderByDescending(x => x.Count);
-
- if (sameAddressCoins.Any())
- {
- // Select between 2 and MaxInputsRegistrableByWallet coins that are on reused HdPubKey.
- // First from the max reused HdPubKey then complete with the 2nd max etc... until reaching max or no more coins on reused HdPubKey
- return sameAddressCoins.SelectMany(group => group).Take(MaxInputsRegistrableByWallet).ToImmutableList();
- }
-
Logger.LogDebug($"Coin selection started:");
Logger.LogDebug($"{nameof(filteredCoins)}: {filteredCoins.Length} coins, valued at {Money.Satoshis(filteredCoins.Sum(x => x.Amount)).ToString(false, true)} BTC.");
Logger.LogDebug($"{nameof(privateCoins)}: {privateCoins.Length} coins, valued at {Money.Satoshis(privateCoins.Sum(x => x.Amount)).ToString(false, true)} BTC.");
@@ -905,6 +891,20 @@ public class CoinJoinClient
Logger.LogDebug($"{nameof(winner)}: {winner.Count} coins, {string.Join(", ", winner.Select(x => x.Amount.ToString(false, true)).ToArray())} BTC.");
}
+ foreach (var coin in winner)
+ {
+ // Get all other coins on the same address in case some winners are on a reused address
+ var otherCoinsOnSameAddress = semiPrivateCoins
+ .Union(redCoins)
+ .Where(x => x.HdPubKey == coin.HdPubKey && x != coin);
+ // Add these coins to the winner by respecting MaxInputsRegistrableByWallet
+ winner = winner.Union(otherCoinsOnSameAddress.Take(MaxInputsRegistrableByWallet - winner.Count)).ToList();
+ if (winner.Count >= MaxInputsRegistrableByWallet)
+ {
+ break;
+ }
+ }
+
return winner.ToShuffled().ToImmutableList();
}

different concept: check if winners are on reused addresses and add the coins