Any receive should start from anonset 1
MODIFY
WalletWasabi.Backend/WalletWasabi.Backend.csproj
WalletWasabi.Backend/WalletWasabi.Backend.csproj
<TargetFramework>net5.0</TargetFramework>
<AnalysisLevel>latest</AnalysisLevel>
<LangVersion>latest</LangVersion>
- <NoWarn>1701;1702;1705;1591;1573;CA1031</NoWarn>
+ <NoWarn>1701;1702;1705;1591;1573;CA1031;CA1822</NoWarn>
<Product>WalletWasabiApi</Product>
<Copyright>MIT</Copyright>
<PackageTags>walletwasabi, wasabiwallet, wasabi, hiddenwallet, wallet, bitcoin, hbitcoin, nbitcoin, magicalcryptowallet, magicalwallet, tor, chaum, chaumian, zerolink, coinjoin, fungibility, privacy, anonymity</PackageTags>

MODIFY
WalletWasabi.Gui/WalletWasabi.Gui.csproj
WalletWasabi.Gui/WalletWasabi.Gui.csproj
<TargetFramework>net5.0</TargetFramework>
<AnalysisLevel>latest</AnalysisLevel>
<LangVersion>latest</LangVersion>
- <NoWarn>1701;1702;1705;1591;1573;CA1031</NoWarn>
+ <NoWarn>1701;1702;1705;1591;1573;CA1031;CA1822</NoWarn>
<Nullable>enable</Nullable>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>

MODIFY
WalletWasabi.Packager/WalletWasabi.Packager.csproj
WalletWasabi.Packager/WalletWasabi.Packager.csproj
<TargetFramework>net5.0</TargetFramework>
<AnalysisLevel>latest</AnalysisLevel>
<LangVersion>latest</LangVersion>
- <NoWarn>1701;1702;1705;1591;1573;CA1031</NoWarn>
+ <NoWarn>1701;1702;1705;1591;1573;CA1031;CA1822</NoWarn>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Nullable>enable</Nullable>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>

MODIFY
WalletWasabi.Tests/UnitTests/BlockchainAnalysis/CoinJoinAnonscoreTests.cs
WalletWasabi.Tests/UnitTests/BlockchainAnalysis/CoinJoinAnonscoreTests.cs
@@ -11,7 +11,7 @@ using Xunit;
namespace WalletWasabi.Tests.UnitTests.BlockchainAnalysis
{
- public class CoinJoinAnonscoreTests
+ public class CoinJoinAnonScoreTests
{
[Fact]
public void BasicCalculation()

RENAME
WalletWasabi.Tests/UnitTests/BlockchainAnalysis/PubKeyReuseTests.cs
WalletWasabi.Tests/UnitTests/BlockchainAnalysis/PubKeyReuseAnonScoreTests.cs
@@ -9,7 +9,7 @@ using Xunit;
namespace WalletWasabi.Tests.UnitTests.BlockchainAnalysis
{
- public class PubKeyReuseTests
+ public class PubKeyReuseAnonScoreTests
{
[Fact]
public void AddressReusePunishment()

ADD
WalletWasabi.Tests/UnitTests/BlockchainAnalysis/ReceiveAnonScoreTests.cs
+using NBitcoin;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WalletWasabi.Blockchain.Keys;
+using WalletWasabi.Tests.Helpers;
+using Xunit;
+
+namespace WalletWasabi.Tests.UnitTests.BlockchainAnalysis
+{
+ /// <summary>
+ /// In these tests no inputs of a transaction are controlled by the user.
+ /// </summary>
+ public class ReceiveAnonScoreTests
+ {
+ [Fact]
+ public void NormalReceive()
+ {
+ var analyser = ServiceFactory.CreateBlockchainAnalyzer();
+ var tx = BitcoinFactory.CreateSmartTransaction(1, 1, 0, 1);
+
+ analyser.Analyze(tx);
+
+ var coin = Assert.Single(tx.WalletOutputs);
+ Assert.Equal(1, coin.HdPubKey.AnonymitySet);
+ }
+
+ [Fact]
+ public void WholeCoinReceive()
+ {
+ var analyser = ServiceFactory.CreateBlockchainAnalyzer();
+ var tx = BitcoinFactory.CreateSmartTransaction(1, 0, 0, 1);
+
+ analyser.Analyze(tx);
+
+ var coin = Assert.Single(tx.WalletOutputs);
+ Assert.Equal(1, coin.HdPubKey.AnonymitySet);
+ }
+
+ [Fact]
+ public void CoinjoinReceive()
+ {
+ var analyser = ServiceFactory.CreateBlockchainAnalyzer();
+ var tx = BitcoinFactory.CreateSmartTransaction(10, Enumerable.Repeat(Money.Coins(1m), 9), Enumerable.Empty<(Money, int)>(), new[] { (Money.Coins(1m), HdPubKey.DefaultHighAnonymitySet) });
+
+ analyser.Analyze(tx);
+
+ var coin = Assert.Single(tx.WalletOutputs);
+ Assert.Equal(1, coin.HdPubKey.AnonymitySet);
+ }
+ }
+}

MODIFY
WalletWasabi.Tests/WalletWasabi.Tests.csproj
WalletWasabi.Tests/WalletWasabi.Tests.csproj
<AnalysisLevel>latest</AnalysisLevel>
<IsPackable>false</IsPackable>
<LangVersion>latest</LangVersion>
- <NoWarn>1701;1702;1705;1591;CA1031</NoWarn>
+ <NoWarn>1701;1702;1705;1591;CA1031;CA1822</NoWarn>
<ApplicationIcon />
<OutputType>Library</OutputType>
<StartupObject />

MODIFY
WalletWasabi/Blockchain/Analysis/BlockchainAnalyzer.cs
WalletWasabi/Blockchain/Analysis/BlockchainAnalyzer.cs
@@ -28,7 +28,11 @@ namespace WalletWasabi.Blockchain.Analysis
var ownInputCount = tx.WalletInputs.Count;
var ownOutputCount = tx.WalletOutputs.Count;
- if (inputCount == ownInputCount)
+ if (ownInputCount == 0)
+ {
+ AnalyzeReceive(tx);
+ }
+ else if (inputCount == ownInputCount)
{
if (outputCount == ownOutputCount)
{
@@ -113,6 +117,15 @@ namespace WalletWasabi.Blockchain.Analysis
}
}
+ private static void AnalyzeReceive(SmartTransaction tx)
+ {
+ // No matter how much anonymity a user would had gained in a tx, if the money comes from outside, then make anonset 1.
+ foreach (var key in tx.WalletOutputs.Select(x => x.HdPubKey))
+ {
+ key.AnonymitySet = 1;
+ }
+ }
+
private static void AnalyzeNormalSpend(SmartTransaction tx)
{
// If all our inputs are ours and there's more than one output that isn't,

MODIFY
WalletWasabi/WalletWasabi.csproj
WalletWasabi/WalletWasabi.csproj
<AnalysisLevel>latest</AnalysisLevel>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<LangVersion>latest</LangVersion>
- <NoWarn>1701;1702;1705;1591;1573;CA1031</NoWarn>
+ <NoWarn>1701;1702;1705;1591;1573;CA1031;CA1822</NoWarn>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Nullable>enable</Nullable>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>

Any receive should start from anonset 1