Ensure valid groups
MODIFY
WalletWasabi.Tests/UnitTests/WabiSabi/Client/AmountDecomposerTests.cs
WalletWasabi.Tests/UnitTests/WabiSabi/Client/AmountDecomposerTests.cs
@@ -28,13 +28,13 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Client
[InlineData(5000, 0, 8)]
public void DecompositionsInvariantTest(decimal feeRateDecimal, long minOutputAmount, int maxAvailableOutputs)
{
- var availableVsize = maxAvailableOutputs * Constants.P2WPKHOutputSizeInBytes;
+ var availableVsize = maxAvailableOutputs * Constants.P2wpkhOutputSizeInBytes;
var feeRate = new FeeRate(feeRateDecimal);
- var feePerOutput = feeRate.GetFee(Constants.P2WPKHOutputSizeInBytes);
+ var feePerOutput = feeRate.GetFee(Constants.P2wpkhOutputSizeInBytes);
var registeredCoins = GenerateRandomCoins().Take(3).ToList();
var theirCoins = GenerateRandomCoins().Take(30).ToList();
- var amountDecomposer = new AmountDecomposer(feeRate, minOutputAmount, Constants.P2WPKHOutputSizeInBytes, availableVsize);
+ var amountDecomposer = new AmountDecomposer(feeRate, minOutputAmount, Constants.P2wpkhOutputSizeInBytes, availableVsize);
var outputValues = amountDecomposer.Decompose(registeredCoins, theirCoins);
var totalEffectiveValue = registeredCoins.Sum(x => x.EffectiveValue(feeRate));

MODIFY
WalletWasabi/Helpers/Constants.cs
WalletWasabi/Helpers/Constants.cs
@@ -20,8 +20,12 @@ namespace WalletWasabi.Helpers
public const int P2wpkhInputSizeInBytes = 41;
public const int P2wpkhInputVirtualSize = 69;
public const int P2pkhInputSizeInBytes = 145;
+ public const int P2wpkhOutputSizeInBytes = 31;
+
+ /// <summary>
+ /// OBSOLATED, USE SPECIFIC TYPE
+ /// </summary>
public const int OutputSizeInBytes = 33;
- public const int P2WPKHOutputSizeInBytes = 31;
// https://en.bitcoin.it/wiki/Bitcoin
// There are a maximum of 2,099,999,997,690,000 Bitcoin elements (called satoshis), which are currently most commonly measured in units of 100,000,000 known as BTC. Stated another way, no more than 21 million BTC can ever be created.

MODIFY
WalletWasabi/WabiSabi/Client/CoinJoinClient.cs
WalletWasabi/WabiSabi/Client/CoinJoinClient.cs
@@ -118,7 +118,7 @@ namespace WalletWasabi.WabiSabi.Client
// Calculate outputs values
roundState = await RoundStatusUpdater.CreateRoundAwaiter(rs => rs.Id == roundState.Id, cancellationToken).ConfigureAwait(false);
constructionState = roundState.Assert<ConstructionState>();
- AmountDecomposer amountDecomposer = new(roundState.FeeRate, roundState.CoinjoinState.Parameters.AllowedOutputAmounts.Min, Constants.P2WPKHOutputSizeInBytes, (int)availableVsize);
+ AmountDecomposer amountDecomposer = new(roundState.FeeRate, roundState.CoinjoinState.Parameters.AllowedOutputAmounts.Min, Constants.P2wpkhOutputSizeInBytes, (int)availableVsize);
var theirCoins = constructionState.Inputs.Except(registeredCoins);
var outputValues = amountDecomposer.Decompose(registeredCoins, theirCoins);
@@ -334,9 +334,15 @@ namespace WalletWasabi.WabiSabi.Client
// I can take more coins those are already reached the minimum privacy threshold.
for (int i = 0; i < nonPrivateCoinCount; i++)
{
+ // Make sure the group can at least register an output even after paying fees.
var group = filteredCoins.Skip(i).Take(inputCount);
+ var inSum = group.Sum(x => x.EffectiveValue(parameters.FeeRate));
+ var outFee = parameters.FeeRate.GetFee(Constants.P2wpkhOutputSizeInBytes);
+ if (inSum >= outFee + parameters.AllowedOutputAmounts.Min)
+ {
groups.Add(group);
}
+ }
// Calculate the anonScore cost of input consolidation.
List<(long Cost, IEnumerable<SmartCoin> Group)> anonScoreCosts = new();

Ensure valid groups