Privacy level threshold for clustering
MODIFY
WalletWasabi/Models/CoinsRegistry.cs
WalletWasabi/Models/CoinsRegistry.cs
@@ -14,14 +14,16 @@ namespace WalletWasabi.Models
private object Lock { get; set; }
private HashSet<SmartCoin> SpentCoins { get; }
private Dictionary<Script, Cluster> ClustersByScriptPubKey { get; }
+ private int PrivacyLevelThreshold { get; }
- public CoinsRegistry()
+ public CoinsRegistry(int privacyLevelThreshold)
{
Coins = new HashSet<SmartCoin>();
SpentCoins = new HashSet<SmartCoin>();
LatestCoinsSnapshot = new HashSet<SmartCoin>();
InvalidateSnapshot = false;
ClustersByScriptPubKey = new Dictionary<Script, Cluster>();
+ PrivacyLevelThreshold = privacyLevelThreshold;
Lock = new object();
}
@@ -90,7 +92,7 @@ namespace WalletWasabi.Models
var createdCoins = Coins.Where(x => x.TransactionId == spentCoin.SpenderTransactionId);
foreach (var newCoin in createdCoins)
{
- if (newCoin.AnonymitySet < 50)
+ if (newCoin.AnonymitySet < PrivacyLevelThreshold)
{
spentCoin.Clusters.Merge(newCoin.Clusters);
newCoin.Clusters = spentCoin.Clusters;

MODIFY
WalletWasabi/Services/TransactionProcessor.cs
WalletWasabi/Services/TransactionProcessor.cs
@@ -27,12 +27,13 @@ namespace WalletWasabi.Services
public TransactionProcessor(
AllTransactionStore transactionStore,
KeyManager keyManager,
- Money dustThreshold)
+ Money dustThreshold,
+ int privacyLevelThreshold = 100)
{
TransactionStore = Guard.NotNull(nameof(transactionStore), transactionStore);
KeyManager = Guard.NotNull(nameof(keyManager), keyManager);
DustThreshold = Guard.NotNull(nameof(dustThreshold), dustThreshold);
- Coins = new CoinsRegistry();
+ Coins = new CoinsRegistry(privacyLevelThreshold);
}
public bool Process(SmartTransaction tx)

MODIFY
WalletWasabi/Services/WalletService.cs
WalletWasabi/Services/WalletService.cs
@@ -108,7 +108,7 @@ namespace WalletWasabi.Services
KeyManager.AssertCleanKeysIndexed();
KeyManager.AssertLockedInternalKeysIndexed(14);
- TransactionProcessor = new TransactionProcessor(BitcoinStore.TransactionStore, KeyManager, ServiceConfiguration.DustThreshold);
+ TransactionProcessor = new TransactionProcessor(BitcoinStore.TransactionStore, KeyManager, ServiceConfiguration.DustThreshold, ServiceConfiguration.PrivacyLevelStrong);
Coins = TransactionProcessor.Coins;
TransactionProcessor.CoinSpent += TransactionProcessor_CoinSpent;
TransactionProcessor.CoinReceived += TransactionProcessor_CoinReceivedAsync;
@@ -364,75 +364,6 @@ namespace WalletWasabi.Services
return ret;
}
- public List<SmartCoin> GetClusters(SmartCoin coin, List<SmartCoin> current, ILookup<Script, SmartCoin> lookupScriptPubKey, ILookup<uint256, SmartCoin> lookupSpenderTransactionId, ILookup<uint256, SmartCoin> lookupTransactionId)
- {
- Guard.NotNull(nameof(coin), coin);
- if (current.Contains(coin))
- {
- return current;
- }
-
- var clusters = current.Concat(new List<SmartCoin> { coin }).ToList(); // The coin is the first elem in its cluster.
-
- // If the script is the same then we have a match, no matter of the anonymity set.
- foreach (var c in lookupScriptPubKey[coin.ScriptPubKey])
- {
- if (!clusters.Contains(c))
- {
- var h = GetClusters(c, clusters, lookupScriptPubKey, lookupSpenderTransactionId, lookupTransactionId);
- foreach (var hr in h)
- {
- if (!clusters.Contains(hr))
- {
- clusters.Add(hr);
- }
- }
- }
- }
-
- // If it spends someone and has not been sufficiently anonymized.
- if (coin.AnonymitySet < ServiceConfiguration.PrivacyLevelStrong)
- {
- var c = lookupSpenderTransactionId[coin.TransactionId].FirstOrDefault(x => !clusters.Contains(x));
- if (c != default)
- {
- var h = GetClusters(c, clusters, lookupScriptPubKey, lookupSpenderTransactionId, lookupTransactionId);
- foreach (var hr in h)
- {
- if (!clusters.Contains(hr))
- {
- clusters.Add(hr);
- }
- }
- }
- }
-
- // If it's being spent by someone and that someone has not been sufficiently anonymized.
- if (!coin.Unspent)
- {
- var c = lookupTransactionId[coin.SpenderTransactionId].FirstOrDefault(x => !clusters.Contains(x));
- if (c != default)
- {
- if (c.AnonymitySet < ServiceConfiguration.PrivacyLevelStrong)
- {
- if (c != default)
- {
- var h = GetClusters(c, clusters, lookupScriptPubKey, lookupSpenderTransactionId, lookupTransactionId);
- foreach (var hr in h)
- {
- if (!clusters.Contains(hr))
- {
- clusters.Add(hr);
- }
- }
- }
- }
- }
- }
-
- return clusters;
- }
-
private void ProcessBlock(Height height, Block block, IEnumerable<int> filterByTxIndexes = null, IEnumerable<SmartTransaction> skeletonBlock = null)
{
lock (TransactionProcessingLock)

Privacy level threshold for clustering