Make DoS duration configurable
MODIFY
WalletWasabi.Backend/Controllers/ChaumianCoinJoinController.cs
WalletWasabi.Backend/Controllers/ChaumianCoinJoinController.cs
@@ -157,8 +157,8 @@ namespace WalletWasabi.Backend.Controllers
OutPoint outpoint = inputProof.Input.ToOutPoint();
if (Coordinator.UtxoReferee.BannedUtxos.TryGetValue(outpoint, out (int severity, DateTimeOffset timeOfBan) bannedElem))
{
- int maxBan = (int)TimeSpan.FromDays(30).TotalMinutes;
- int banLeft = maxBan - (int)((DateTimeOffset.UtcNow - bannedElem.timeOfBan).TotalMinutes);
+ int maxBan = (int)TimeSpan.FromHours((long)Global.RoundConfig.DosDurationHours).TotalMinutes;
+ int banLeft = maxBan - (int)(DateTimeOffset.UtcNow - bannedElem.timeOfBan).TotalMinutes;
if (banLeft > 0)
{
return BadRequest($"Input is banned from participation for {banLeft} minutes: {inputProof.Input.Index}:{inputProof.Input.TransactionId}.");

MODIFY
WalletWasabi.Tests/RegTests.cs
WalletWasabi.Tests/RegTests.cs
@@ -1654,7 +1654,7 @@ namespace WalletWasabi.Tests
decimal coordinatorFeePercent = 0.2m;
int anonymitySet = 2;
int connectionConfirmationTimeout = 50;
- var roundConfig = new CcjRoundConfig(denomination, 2, coordinatorFeePercent, anonymitySet, 100, connectionConfirmationTimeout, 50, 50, 2);
+ var roundConfig = new CcjRoundConfig(denomination, 2, coordinatorFeePercent, anonymitySet, 100, connectionConfirmationTimeout, 50, 50, 2, 24);
coordinator.UpdateRoundConfig(roundConfig);
coordinator.AbortAllRoundsInInputRegistration(nameof(RegTests), "");
@@ -2123,7 +2123,7 @@ namespace WalletWasabi.Tests
decimal coordinatorFeePercent = 0.1m;
int anonymitySet = 3;
int connectionConfirmationTimeout = 120;
- var roundConfig = new CcjRoundConfig(denomination, 140, coordinatorFeePercent, anonymitySet, 240, connectionConfirmationTimeout, 1, 1, 1);
+ var roundConfig = new CcjRoundConfig(denomination, 140, coordinatorFeePercent, anonymitySet, 240, connectionConfirmationTimeout, 1, 1, 1, 24);
coordinator.UpdateRoundConfig(roundConfig);
coordinator.AbortAllRoundsInInputRegistration(nameof(RegTests), "");
await rpc.GenerateAsync(3); // So to make sure we have enough money.
@@ -2259,7 +2259,7 @@ namespace WalletWasabi.Tests
decimal coordinatorFeePercent = 0.003m;
int anonymitySet = 100;
int connectionConfirmationTimeout = 120;
- var roundConfig = new CcjRoundConfig(denomination, 144, coordinatorFeePercent, anonymitySet, 240, connectionConfirmationTimeout, 50, 50, 1);
+ var roundConfig = new CcjRoundConfig(denomination, 144, coordinatorFeePercent, anonymitySet, 240, connectionConfirmationTimeout, 50, 50, 1, 24);
coordinator.UpdateRoundConfig(roundConfig);
coordinator.AbortAllRoundsInInputRegistration(nameof(RegTests), "");
await rpc.GenerateAsync(100); // So to make sure we have enough money.
@@ -2466,7 +2466,7 @@ namespace WalletWasabi.Tests
decimal coordinatorFeePercent = 0.1m;
int anonymitySet = 2;
int connectionConfirmationTimeout = 14;
- var roundConfig = new CcjRoundConfig(denomination, 140, coordinatorFeePercent, anonymitySet, 240, connectionConfirmationTimeout, 50, 50, 1);
+ var roundConfig = new CcjRoundConfig(denomination, 140, coordinatorFeePercent, anonymitySet, 240, connectionConfirmationTimeout, 50, 50, 1, 24);
coordinator.UpdateRoundConfig(roundConfig);
coordinator.AbortAllRoundsInInputRegistration(nameof(RegTests), "");
await rpc.GenerateAsync(3); // So to make sure we have enough money.
@@ -2566,7 +2566,7 @@ namespace WalletWasabi.Tests
// Make sure if times out, it tries again.
connectionConfirmationTimeout = 1;
- roundConfig = new CcjRoundConfig(denomination, 140, coordinatorFeePercent, anonymitySet, 240, connectionConfirmationTimeout, 50, 50, 1);
+ roundConfig = new CcjRoundConfig(denomination, 140, coordinatorFeePercent, anonymitySet, 240, connectionConfirmationTimeout, 50, 50, 1, 24);
coordinator.UpdateRoundConfig(roundConfig);
coordinator.AbortAllRoundsInInputRegistration(nameof(RegTests), "");
Assert.NotEmpty(chaumianClient1.State.GetAllQueuedCoins());
@@ -2611,7 +2611,7 @@ namespace WalletWasabi.Tests
decimal coordinatorFeePercent = 0.1m;
int anonymitySet = 2;
int connectionConfirmationTimeout = 14;
- var roundConfig = new CcjRoundConfig(denomination, 140, coordinatorFeePercent, anonymitySet, 240, connectionConfirmationTimeout, 50, 50, 1);
+ var roundConfig = new CcjRoundConfig(denomination, 140, coordinatorFeePercent, anonymitySet, 240, connectionConfirmationTimeout, 50, 50, 1, 24);
coordinator.UpdateRoundConfig(roundConfig);
coordinator.AbortAllRoundsInInputRegistration(nameof(RegTests), "");
await rpc.GenerateAsync(3); // So to make sure we have enough money.
@@ -2708,7 +2708,7 @@ namespace WalletWasabi.Tests
decimal coordinatorFeePercent = 0.1m;
int anonymitySet = 2;
int connectionConfirmationTimeout = 14;
- var roundConfig = new CcjRoundConfig(denomination, 140, coordinatorFeePercent, anonymitySet, 240, connectionConfirmationTimeout, 50, 50, 1);
+ var roundConfig = new CcjRoundConfig(denomination, 140, coordinatorFeePercent, anonymitySet, 240, connectionConfirmationTimeout, 50, 50, 1, 24);
coordinator.UpdateRoundConfig(roundConfig);
coordinator.AbortAllRoundsInInputRegistration(nameof(RegTests), "");

MODIFY
WalletWasabi.Tests/XunitConfiguration/RegTestFixture.cs
WalletWasabi.Tests/XunitConfiguration/RegTestFixture.cs
@@ -33,7 +33,7 @@ namespace WalletWasabi.Tests.XunitConfiguration
var config = new Config(rpc.Network, authString[0], authString[1]);
- var roundConfig = new CcjRoundConfig(Money.Coins(0.1m), 144, 0.1m, 100, 120, 60, 60, 60, 1);
+ var roundConfig = new CcjRoundConfig(Money.Coins(0.1m), 144, 0.1m, 100, 120, 60, 60, 60, 1, 24);
Global.InitializeAsync(config, roundConfig, rpc).GetAwaiter().GetResult();

MODIFY
WalletWasabi/Models/ChaumianCoinJoin/CcjRoundConfig.cs
WalletWasabi/Models/ChaumianCoinJoin/CcjRoundConfig.cs
@@ -45,6 +45,9 @@ namespace WalletWasabi.Models.ChaumianCoinJoin
[JsonProperty(PropertyName = "DosSeverity")]
public int? DosSeverity { get; internal set; }
+ [JsonProperty(PropertyName = "DosDurationHours")]
+ public long? DosDurationHours { get; internal set; }
+
public CcjRoundConfig()
{
}
@@ -54,7 +57,7 @@ namespace WalletWasabi.Models.ChaumianCoinJoin
SetFilePath(filePath);
}
- public CcjRoundConfig(Money denomination, int? confirmationTarget, decimal? coordinatorFeePercent, int? anonymitySet, long? inputRegistrationTimeout, long? connectionConfirmationTimeout, long? outputRegistrationTimeout, long? signingTimeout, int? dosSeverity)
+ public CcjRoundConfig(Money denomination, int? confirmationTarget, decimal? coordinatorFeePercent, int? anonymitySet, long? inputRegistrationTimeout, long? connectionConfirmationTimeout, long? outputRegistrationTimeout, long? signingTimeout, int? dosSeverity, long? dosDurationHours)
{
FilePath = null;
Denomination = Guard.NotNull(nameof(denomination), denomination);
@@ -66,6 +69,7 @@ namespace WalletWasabi.Models.ChaumianCoinJoin
OutputRegistrationTimeout = Guard.NotNull(nameof(outputRegistrationTimeout), outputRegistrationTimeout);
SigningTimeout = Guard.NotNull(nameof(signingTimeout), signingTimeout);
DosSeverity = Guard.NotNull(nameof(dosSeverity), dosSeverity);
+ DosDurationHours = Guard.NotNull(nameof(dosDurationHours), dosDurationHours);
}
/// <inheritdoc />
@@ -93,6 +97,7 @@ namespace WalletWasabi.Models.ChaumianCoinJoin
OutputRegistrationTimeout = 60;
SigningTimeout = 60;
DosSeverity = 1;
+ DosDurationHours = 730; // 1 month
if (!File.Exists(FilePath))
{
@@ -112,6 +117,7 @@ namespace WalletWasabi.Models.ChaumianCoinJoin
OutputRegistrationTimeout = config.OutputRegistrationTimeout ?? OutputRegistrationTimeout;
SigningTimeout = config.SigningTimeout ?? SigningTimeout;
DosSeverity = config.DosSeverity ?? DosSeverity;
+ DosDurationHours = config.DosDurationHours ?? DosDurationHours;
}
await ToFileAsync();
@@ -166,6 +172,10 @@ namespace WalletWasabi.Models.ChaumianCoinJoin
{
return true;
}
+ if (DosDurationHours != config.DosDurationHours)
+ {
+ return true;
+ }
return false;
}

Make DoS duration configurable