Improve GetMaxSuggestedAmount logic
MODIFY
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/Rounds/MultipartyTransactionStateTests.cs
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/Rounds/MultipartyTransactionStateTests.cs
@@ -72,25 +72,23 @@ public class MultipartyTransactionStateTests
Assert.Equal(clientState3.Outputs, state3.Outputs);
}
- [Fact]
- public void GetSuggestedAmountsTest()
- {
- Money baseAmount = Money.Coins(0.1m);
-
- for (int i = 0; i < 100; i++)
+ [Theory]
+ [InlineData(32, "1343.75")]
+ [InlineData(32 + 32, "1343.75")]
+ [InlineData(16, "1000")]
+ [InlineData(16 + 32, "1000")]
+ [InlineData(8, "100")]
+ [InlineData(8 + 32, "100")]
+ [InlineData(4, "10")]
+ [InlineData(4 + 32, "10")]
+ [InlineData(2, "1")]
+ [InlineData(2 + 32, "1")]
+ [InlineData(1, "0.1")]
+ [InlineData(1 + 32, "0.1")]
+ [InlineData(0, "0.1")]
+ public void GetSuggestedAmountsTest(int roundCounter, string amount)
{
- var expected = i switch
- {
- 0 => baseAmount,
- var n when (n % 32 == 0) => baseAmount * 100000,
- var n when (n % 16 == 0) => baseAmount * 10000,
- var n when (n % 8 == 0) => baseAmount * 1000,
- var n when (n % 4 == 0) => baseAmount * 100,
- var n when (n % 2 == 0) => baseAmount * 10,
- _ => baseAmount,
- };
-
- Assert.Equal(expected, Arena.GetMaxSuggestedAmount(i));
- }
+ var expected = Money.Coins(decimal.Parse(amount));
+ Assert.Equal(expected, RoundHelpers.GetMaxSuggestedAmount(roundCounter));
}
}

MODIFY
WalletWasabi/WabiSabi/Backend/Rounds/Arena.cs
WalletWasabi/WabiSabi/Backend/Rounds/Arena.cs
@@ -348,28 +348,19 @@ public partial class Arena : PeriodicRunner
{
var feeRate = (await Rpc.EstimateSmartFeeAsync((int)Config.ConfirmationTarget, EstimateSmartFeeMode.Conservative, simulateIfRegTest: true, cancellationToken).ConfigureAwait(false)).FeeRate;
- RoundParameters roundParams = new(Config, Network, Random, feeRate, Config.CoordinationFeeRate, GetMaxSuggestedAmount(ConnectionConfirmationStartedCounter));
+ RoundParameters roundParams = new(
+ Config,
+ Network,
+ Random,
+ feeRate,
+ Config.CoordinationFeeRate,
+ RoundHelpers.GetMaxSuggestedAmount(ConnectionConfirmationStartedCounter));
Round r = new(roundParams);
Rounds.Add(r);
+ r.LogInfo($"Created round with params: {nameof(RoundParameters.MaxRegistrableAmount)}:'{roundParams.MaxRegistrableAmount}'.");
}
}
- internal static Money GetMaxSuggestedAmount(int roundCounter)
- {
- Money baseAmount = Money.Coins(0.1m);
-
- return roundCounter switch
- {
- 0 => baseAmount,
- var n when (n % 32 == 0) => baseAmount * 100000,
- var n when (n % 16 == 0) => baseAmount * 10000,
- var n when (n % 8 == 0) => baseAmount * 1000,
- var n when (n % 4 == 0) => baseAmount * 100,
- var n when (n % 2 == 0) => baseAmount * 10,
- _ => baseAmount,
- };
- }
-
private void TimeoutRounds()
{
foreach (var expiredRound in Rounds.Where(

ADD
WalletWasabi/WabiSabi/Backend/Rounds/RoundHelpers.cs
+using NBitcoin;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace WalletWasabi.WabiSabi.Backend.Rounds;
+
+internal class RoundHelpers
+{
+ private static List<(int Divider, Money MaxValue)>? RoundCounterDividerAndMaxAmountsCache;
+
+ private static List<(int Divider, Money MaxValue)> RoundCounterDividerAndMaxAmounts
+ {
+ get
+ {
+ if (RoundCounterDividerAndMaxAmountsCache == null)
+ {
+ RoundCounterDividerAndMaxAmountsCache = GenerateRoundCounterDividerAndMaxAmounts();
+ }
+ return RoundCounterDividerAndMaxAmountsCache;
+ }
+ }
+
+ private static List<(int Divider, Money MaxValue)> GenerateRoundCounterDividerAndMaxAmounts()
+ {
+ Money smallestMaximum = Money.Coins(0.1m);
+ Money absoluteMaximumInput = Money.Satoshis(ProtocolConstants.MaxAmountPerAlice);
+
+ int level = 0;
+ List<(int Divider, Money MaxValue)> roundCounterDividerAndMaxAmounts = new();
+ bool end = false;
+ do
+ {
+ var roundDivider = (int)Math.Pow(2, level);
+ var maxValue = smallestMaximum * (long)Math.Pow(10, level);
+ if (maxValue >= absoluteMaximumInput)
+ {
+ maxValue = absoluteMaximumInput;
+ end = true;
+ }
+ roundCounterDividerAndMaxAmounts.Insert(0, (roundDivider, maxValue));
+ level++;
+ }
+ while (!end);
+
+ return roundCounterDividerAndMaxAmounts;
+ }
+
+ public static Money GetMaxSuggestedAmount(int roundCounter)
+ {
+ if (roundCounter != 0)
+ {
+ foreach (var (divider, maxValue) in RoundCounterDividerAndMaxAmounts)
+ {
+ if (roundCounter % divider == 0)
+ {
+ return maxValue;
+ }
+ }
+ }
+
+ return RoundCounterDividerAndMaxAmounts.Last().MaxValue;
+ }
+}

Improve GetMaxSuggestedAmount logic