Move Min/Max AnonScoreTarget to wallet settings
MODIFY
WalletWasabi.Fluent/Config.cs
WalletWasabi.Fluent/Config.cs
@@ -18,16 +18,11 @@ namespace WalletWasabi.Fluent;
[JsonObject(MemberSerialization.OptIn)]
public class Config : ConfigBase
{
- public const int DefaultMinAnonScoreTarget = 5;
- public const int DefaultMaxAnonScoreTarget = 10;
-
public const int DefaultJsonRpcServerPort = 37128;
public static readonly Money DefaultDustThreshold = Money.Coins(Constants.DefaultDustThreshold);
private Uri? _backendUri = null;
private Uri? _fallbackBackendUri;
- private int _minAnonScoreTarget;
- private int _maxAnonScoreTarget;
/// <summary>
/// Constructor for config population using Newtonsoft.JSON.
@@ -39,7 +34,7 @@ public class Config : ConfigBase
public Config(string filePath) : base(filePath)
{
- ServiceConfiguration = new ServiceConfiguration(MinAnonScoreTarget, MaxAnonScoreTarget, GetBitcoinP2pEndPoint(), DustThreshold);
+ ServiceConfiguration = new ServiceConfiguration(GetBitcoinP2pEndPoint(), DustThreshold);
}
[JsonProperty(PropertyName = "Network")]
@@ -116,42 +111,6 @@ public class Config : ConfigBase
"http://localhost:37128/"
};
- [DefaultValue(DefaultMinAnonScoreTarget)]
- [JsonProperty(PropertyName = "MinAnonScoreTarget", DefaultValueHandling = DefaultValueHandling.Populate)]
- public int MinAnonScoreTarget
- {
- get => _minAnonScoreTarget;
- internal set
- {
- if (_minAnonScoreTarget != value)
- {
- _minAnonScoreTarget = value;
- if (ServiceConfiguration is { })
- {
- ServiceConfiguration.MinAnonScoreTarget = value;
- }
- }
- }
- }
-
- [DefaultValue(DefaultMaxAnonScoreTarget)]
- [JsonProperty(PropertyName = "MaxAnonScoreTarget", DefaultValueHandling = DefaultValueHandling.Populate)]
- public int MaxAnonScoreTarget
- {
- get => _maxAnonScoreTarget;
- internal set
- {
- if (_maxAnonScoreTarget != value)
- {
- _maxAnonScoreTarget = value;
- if (ServiceConfiguration is { })
- {
- ServiceConfiguration.MaxAnonScoreTarget = value;
- }
- }
- }
- }
-
[JsonProperty(PropertyName = "DustThreshold")]
[JsonConverter(typeof(MoneyBtcJsonConverter))]
public Money DustThreshold { get; internal set; } = DefaultDustThreshold;
@@ -262,7 +221,7 @@ public class Config : ConfigBase
{
base.LoadFile();
- ServiceConfiguration = new ServiceConfiguration(MinAnonScoreTarget, MaxAnonScoreTarget, GetBitcoinP2pEndPoint(), DustThreshold);
+ ServiceConfiguration = new ServiceConfiguration(GetBitcoinP2pEndPoint(), DustThreshold);
// Just debug convenience.
_backendUri = GetCurrentBackendUri();

MODIFY
WalletWasabi.Fluent/Helpers/CoinHelpers.cs
WalletWasabi.Fluent/Helpers/CoinHelpers.cs
@@ -5,11 +5,10 @@ namespace WalletWasabi.Fluent.Helpers;
public static class CoinHelpers
{
- public static bool IsPrivate(this SmartCoin coin)
+ public static bool IsPrivate(this SmartCoin coin, int privateThreshold)
{
- var privateThreshold = Services.Config.MinAnonScoreTarget;
return coin.HdPubKey.AnonymitySet >= privateThreshold;
}
- public static SmartLabel GetLabels(this SmartCoin coin) => coin.IsPrivate() ? SmartLabel.Empty : coin.HdPubKey.Cluster.Labels;
+ public static SmartLabel GetLabels(this SmartCoin coin, int privateThreshold) => coin.IsPrivate(privateThreshold) ? SmartLabel.Empty : coin.HdPubKey.Cluster.Labels;
}

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Home/Tiles/PrivacyControlTileViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Home/Tiles/PrivacyControlTileViewModel.cs
@@ -90,7 +90,7 @@ public partial class PrivacyControlTileViewModel : TileViewModel
private bool CanCoinJoin()
{
- var privateThreshold = _wallet.ServiceConfiguration.MinAnonScoreTarget;
+ var privateThreshold = _wallet.KeyManager.MinAnonScoreTarget;
return _wallet.Coins.Any(x => x.HdPubKey.AnonymitySet < privateThreshold);
}
@@ -119,7 +119,7 @@ public partial class PrivacyControlTileViewModel : TileViewModel
private void Update()
{
- var privateThreshold = _wallet.ServiceConfiguration.MinAnonScoreTarget;
+ var privateThreshold = _wallet.KeyManager.MinAnonScoreTarget;
var privateAmount = _wallet.Coins.FilterBy(x => x.HdPubKey.AnonymitySet >= privateThreshold).TotalAmount();
var normalAmount = _wallet.Coins.FilterBy(x => x.HdPubKey.AnonymitySet < privateThreshold).TotalAmount();

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Home/Tiles/WalletBalanceTileViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Home/Tiles/WalletBalanceTileViewModel.cs
@@ -56,7 +56,7 @@ public partial class WalletBalanceTileViewModel : TileViewModel
BalanceFiat = _wallet.Coins.TotalAmount().ToDecimal(MoneyUnit.BTC)
.GenerateFiatText(_wallet.Synchronizer.UsdExchangeRate, "USD");
- var privateThreshold = _wallet.ServiceConfiguration.MinAnonScoreTarget;
+ var privateThreshold = _wallet.KeyManager.MinAnonScoreTarget;
var privateCoins = _wallet.Coins.FilterBy(x => x.HdPubKey.AnonymitySet >= privateThreshold);
var normalCoins = _wallet.Coins.FilterBy(x => x.HdPubKey.AnonymitySet < privateThreshold);

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Send/PrivacyControlViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Send/PrivacyControlViewModel.cs
@@ -77,7 +77,7 @@ public partial class PrivacyControlViewModel : DialogViewModelBase<IEnumerable<S
if (!isInHistory)
{
- var pockets = _wallet.Coins.GetPockets(_wallet.ServiceConfiguration.MinAnonScoreTarget).Select(x => new PocketViewModel(x));
+ var pockets = _wallet.Coins.GetPockets(_wallet.KeyManager.MinAnonScoreTarget).Select(x => new PocketViewModel(x));
_pocketSource.AddRange(pockets);
}

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Send/PrivacySuggestionsFlyoutViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Send/PrivacySuggestionsFlyoutViewModel.cs
@@ -43,7 +43,7 @@ public partial class PrivacySuggestionsFlyoutViewModel : ViewModelBase
if (!info.IsPrivate)
{
- Suggestions.Add(new PocketSuggestionViewModel(SmartLabel.Merge(transaction.SpentCoins.Select(x => CoinHelpers.GetLabels(x)))));
+ Suggestions.Add(new PocketSuggestionViewModel(SmartLabel.Merge(transaction.SpentCoins.Select(x => CoinHelpers.GetLabels(x, wallet.KeyManager.MinAnonScoreTarget)))));
}
var suggestions =

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Send/SendViewModel.cs
WalletWasabi.Fluent/ViewModels/Wallets/Send/SendViewModel.cs
@@ -49,7 +49,7 @@ public partial class SendViewModel : RoutableViewModel
{
_to = "";
_wallet = wallet;
- _transactionInfo = new TransactionInfo();
+ _transactionInfo = new TransactionInfo(wallet.KeyManager.MinAnonScoreTarget);
IsQrButtonVisible = WebcamQrReader.IsOsPlatformSupported;

MODIFY
WalletWasabi.Fluent/ViewModels/Wallets/Send/TransactionInfo.cs
WalletWasabi.Fluent/ViewModels/Wallets/Send/TransactionInfo.cs
@@ -14,9 +14,9 @@ public partial class TransactionInfo
[AutoNotify] private Money _amount = Money.Zero;
- public TransactionInfo()
+ public TransactionInfo(int minAnonScoreTarget)
{
- _privateCoinThreshold = Services.Config.MinAnonScoreTarget;
+ _privateCoinThreshold = minAnonScoreTarget;
this.WhenAnyValue(x => x.Amount)
.Subscribe(_ => OnAmountChanged());

MODIFY
WalletWasabi/Blockchain/Keys/KeyManager.cs
WalletWasabi/Blockchain/Keys/KeyManager.cs
@@ -2,6 +2,7 @@ using NBitcoin;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Collections.Immutable;
+using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
@@ -22,6 +23,11 @@ namespace WalletWasabi.Blockchain.Keys;
[JsonObject(MemberSerialization.OptIn)]
public class KeyManager
{
+ public const int DefaultMinAnonScoreTarget = 5;
+ public const int DefaultMaxAnonScoreTarget = 10;
+ private int _minAnonScoreTarget;
+ private int _maxAnonScoreTarget;
+
public const int AbsoluteMinGapLimit = 21;
public const int MaxGapLimit = 10_000;
public static Money DefaultPlebStopThreshold = Money.Coins(0.01m);
@@ -151,6 +157,14 @@ public class KeyManager
[JsonProperty(Order = 12, PropertyName = "Icon")]
public string? Icon { get; private set; }
+ [DefaultValue(DefaultMinAnonScoreTarget)]
+ [JsonProperty(PropertyName = "MinAnonScoreTarget", DefaultValueHandling = DefaultValueHandling.Populate)]
+ public int MinAnonScoreTarget { get; private set; }
+
+ [DefaultValue(DefaultMaxAnonScoreTarget)]
+ [JsonProperty(PropertyName = "MaxAnonScoreTarget", DefaultValueHandling = DefaultValueHandling.Populate)]
+ public int MaxAnonScoreTarget { get; private set; }
+
[JsonProperty(Order = 999)]
private List<HdPubKey> HdPubKeys { get; }

MODIFY
WalletWasabi/Models/ServiceConfiguration.cs
WalletWasabi/Models/ServiceConfiguration.cs
@@ -7,19 +7,14 @@ namespace WalletWasabi.Models;
public class ServiceConfiguration
{
public ServiceConfiguration(
- int minAnonScoreTarget,
- int maxAnonScoreTarget,
+
EndPoint bitcoinCoreEndPoint,
Money dustThreshold)
{
- MinAnonScoreTarget = Guard.NotNull(nameof(minAnonScoreTarget), minAnonScoreTarget);
- MaxAnonScoreTarget = Guard.NotNull(nameof(maxAnonScoreTarget), maxAnonScoreTarget);
BitcoinCoreEndPoint = Guard.NotNull(nameof(bitcoinCoreEndPoint), bitcoinCoreEndPoint);
DustThreshold = Guard.NotNull(nameof(dustThreshold), dustThreshold);
}
- public int MinAnonScoreTarget { get; set; }
- public int MaxAnonScoreTarget { get; set; }
public EndPoint BitcoinCoreEndPoint { get; set; }
public Money DustThreshold { get; set; }
}

MODIFY
WalletWasabi/WabiSabi/Client/CoinJoinManager.cs
WalletWasabi/WabiSabi/Client/CoinJoinManager.cs
@@ -163,11 +163,11 @@ public class CoinJoinManager : BackgroundService
var coins = new CoinsView(openedWallet.Coins
.Available()
.Confirmed()
- .Where(x => x.HdPubKey.AnonymitySet < ServiceConfiguration.MaxAnonScoreTarget)
+ .Where(x => x.HdPubKey.AnonymitySet < openedWallet.KeyManager.MaxAnonScoreTarget)
.Where(x => !CoinRefrigerator.IsFrozen(x)));
// If a small portion of the wallet isn't private, it's better to wait with mixing.
- if (GetPrivacyPercentage(coins) > 0.99)
+ if (GetPrivacyPercentage(coins, openedWallet.KeyManager.MinAnonScoreTarget) > 0.99)
{
return Enumerable.Empty<SmartCoin>();
}
@@ -175,10 +175,8 @@ public class CoinJoinManager : BackgroundService
return coins;
}
- private double GetPrivacyPercentage(CoinsView coins)
+ private double GetPrivacyPercentage(CoinsView coins, int privateThreshold)
{
- var privateThreshold = ServiceConfiguration.MinAnonScoreTarget;
-
var privateAmount = coins.FilterBy(x => x.HdPubKey.AnonymitySet >= privateThreshold).TotalAmount();
var normalAmount = coins.FilterBy(x => x.HdPubKey.AnonymitySet < privateThreshold).TotalAmount();

MODIFY
WalletWasabi/WabiSabi/Client/CoinJoinTrackerFactory.cs
WalletWasabi/WabiSabi/Client/CoinJoinTrackerFactory.cs
@@ -29,7 +29,7 @@ public class CoinJoinTrackerFactory
new KeyChain(wallet.KeyManager, wallet.Kitchen),
new InternalDestinationProvider(wallet.KeyManager),
RoundStatusUpdater,
- wallet.ServiceConfiguration.MinAnonScoreTarget,
+ wallet.KeyManager.MinAnonScoreTarget,
doNotRegisterInLastMinuteTimeLimit: TimeSpan.FromMinutes(1));
return new CoinJoinTracker(wallet, coinJoinClient, coinCandidates, CancellationToken);

MODIFY
WalletWasabi/Wallets/Wallet.cs
WalletWasabi/Wallets/Wallet.cs
@@ -97,7 +97,7 @@ public class Wallet : BackgroundService
public bool AllowManualCoinJoin { get; set; }
public Kitchen Kitchen { get; } = new();
- public ICoinsView NonPrivateCoins => new CoinsView(Coins.Where(c => c.HdPubKey.AnonymitySet < ServiceConfiguration.MinAnonScoreTarget));
+ public ICoinsView NonPrivateCoins => new CoinsView(Coins.Where(c => c.HdPubKey.AnonymitySet < KeyManager.MinAnonScoreTarget));
public bool TryLogin(string password, out string? compatibilityPasswordUsed)
{
@@ -142,7 +142,7 @@ public class Wallet : BackgroundService
ServiceConfiguration = Guard.NotNull(nameof(serviceConfiguration), serviceConfiguration);
FeeProvider = Guard.NotNull(nameof(feeProvider), feeProvider);
- TransactionProcessor = new TransactionProcessor(BitcoinStore.TransactionStore, KeyManager, ServiceConfiguration.DustThreshold, ServiceConfiguration.MinAnonScoreTarget);
+ TransactionProcessor = new TransactionProcessor(BitcoinStore.TransactionStore, KeyManager, ServiceConfiguration.DustThreshold, KeyManager.MinAnonScoreTarget);
Coins = TransactionProcessor.Coins;
TransactionProcessor.WalletRelevantTransactionProcessed += TransactionProcessor_WalletRelevantTransactionProcessed;

Move Min/Max AnonScoreTarget to wallet settings