Implement mix until and customizable anonymity levels
MODIFY
WalletWasabi.Gui/Config.cs
WalletWasabi.Gui/Config.cs
@@ -170,7 +170,6 @@ namespace WalletWasabi.Gui
private int? _privacyLevelSome;
private int? _privacyLevelFine;
private int? _privacyLevelStrong;
- private bool? _autoMix;
public IPEndPoint GetTorSocks5EndPoint()
{

MODIFY
WalletWasabi.Tests/P2pTests.cs
WalletWasabi.Tests/P2pTests.cs
@@ -91,7 +91,7 @@ namespace WalletWasabi.Tests
memPoolService,
nodes,
SharedFixture.DataDir,
- new ServiceConfiguration(false, 50, 2, 21, 50));
+ new ServiceConfiguration(50, 2, 21, 50));
Assert.True(Directory.Exists(blocksFolderPath));
try

MODIFY
WalletWasabi.Tests/RegTests.cs
WalletWasabi.Tests/RegTests.cs
@@ -80,7 +80,7 @@ namespace WalletWasabi.Tests
}
Global.Coordinator.UtxoReferee.Clear();
- var serviceConfiguration = new ServiceConfiguration(false, 50, 2, 21, 50);
+ var serviceConfiguration = new ServiceConfiguration(50, 2, 21, 50);
return ("password", Global.RpcClient, Global.RpcClient.Network, Global.Coordinator, serviceConfiguration);
}

MODIFY
WalletWasabi/Services/CcjClient.cs
WalletWasabi/Services/CcjClient.cs
@@ -65,7 +65,12 @@ namespace WalletWasabi.Services
private CancellationTokenSource Cancel { get; }
- public CcjClient(WasabiSynchronizer synchronizer, Network network, KeyManager keyManager, Uri ccjHostUri, IPEndPoint torSocks5EndPoint = null)
+ public CcjClient(
+ WasabiSynchronizer synchronizer,
+ Network network,
+ KeyManager keyManager,
+ Uri ccjHostUri,
+ IPEndPoint torSocks5EndPoint = null)
{
AccessCache = new ConcurrentDictionary<HdPubKey, DateTimeOffset>();
Network = Guard.NotNull(nameof(network), network);
@@ -429,14 +434,16 @@ namespace WalletWasabi.Services
{
try
{
+ // Select the most suitable coins to regiter.
List<TxoRef> registrableCoins = State.GetRegistrableCoins(
inputRegistrableRound.State.MaximumInputCountPerPeer,
inputRegistrableRound.State.Denomination,
inputRegistrableRound.State.FeePerInputs,
inputRegistrableRound.State.FeePerOutputs).ToList();
- if (registrableCoins.Any())
- {
+ // If there are no suitable coins to register return.
+ if (!registrableCoins.Any()) return;
+
BitcoinAddress changeAddress = null;
var activeOutputAddresses = new List<BitcoinAddress>();
@@ -668,7 +675,6 @@ namespace WalletWasabi.Services
roundRegistered.Registration = registration;
}
- }
catch (Exception ex)
{
Logger.LogError<CcjClient>(ex);
@@ -692,6 +698,7 @@ namespace WalletWasabi.Services
private string Salt { get; set; } = null;
private string Soup { get; set; } = null;
+ private object RefrigeratorLock { get; } = new object();
public async Task<IEnumerable<SmartCoin>> QueueCoinsToMixAsync(string password, params SmartCoin[] coins)
{
@@ -781,19 +788,27 @@ namespace WalletWasabi.Services
return null;
}
- var res = StringCipher.Decrypt(Soup, Salt);
+ string res;
+ lock (RefrigeratorLock)
+ {
+ res = StringCipher.Decrypt(Soup, Salt);
+ }
+
Cook(res);
return res;
}
private void Cook(string ingredients)
+ {
+ lock (RefrigeratorLock)
{
ingredients = ingredients ?? "";
Salt = TokenGenerator.GetUniqueKey(21);
Soup = StringCipher.Encrypt(ingredients, Salt);
}
+ }
public async Task DequeueCoinsFromMixAsync(params TxoRef[] coins)
{

MODIFY
WalletWasabi/Services/WalletService.cs
WalletWasabi/Services/WalletService.cs
@@ -497,7 +497,7 @@ namespace WalletWasabi.Services
TransactionCache.TryAdd(tx);
// If it's a dequeued change, then queue it.
- if (newCoin.Unspent && ChaumianClient.HasIngredients && newCoin.Label == "ZeroLink Change")
+ if (newCoin.Unspent && ChaumianClient.HasIngredients && newCoin.Label.StartsWith("ZeroLink", StringComparison.Ordinal) && newCoin.AnonymitySet < ServiceConfiguration.MixUntilAnonymitySet)
{
Task.Run(async () =>
{
@@ -1056,7 +1056,7 @@ namespace WalletWasabi.Services
public IEnumerable<string> GetNonSpecialLabels()
{
- return Coins.Where(x => !x.Label.StartsWith("ZeroLink"))
+ return Coins.Where(x => !x.Label.StartsWith("ZeroLink", StringComparison.Ordinal))
.SelectMany(x => x.Label.Split(new string[] { Constants.ChangeOfSpecialLabelStart, Constants.ChangeOfSpecialLabelEnd, "(", "," }, StringSplitOptions.RemoveEmptyEntries))
.Select(x => x.Trim())
.Distinct();

Implement mix until and customizable anonymity levels