Simplify timeouts handling
MODIFY
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/PhaseStepping/StepInputRegistrationTests.cs
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/PhaseStepping/StepInputRegistrationTests.cs
@@ -210,7 +210,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend.PhaseStepping
await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));
Assert.Equal(Phase.InputRegistration, round.Phase);
- cfg.StandardInputRegistrationTimeout = TimeSpan.Zero;
+ round.InputRegistrationTimeFrame = round.InputRegistrationTimeFrame with { Duration = TimeSpan.Zero };
await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));
Assert.Equal(Phase.ConnectionConfirmation, round.Phase);

MODIFY
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/PostRequests/RegisterInputFailureTests.cs
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/PostRequests/RegisterInputFailureTests.cs
@@ -123,7 +123,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend.PostRequests
var round = arena.Rounds.First();
var ownershipProof = WabiSabiFactory.CreateOwnershipProof(key, round.Id);
- cfg.StandardInputRegistrationTimeout = TimeSpan.Zero;
+ round.InputRegistrationTimeFrame = round.InputRegistrationTimeFrame with { Duration = TimeSpan.Zero };
var arenaClient = WabiSabiFactory.CreateArenaClient(arena);
var ex = await Assert.ThrowsAsync<WabiSabiProtocolException>(

MODIFY
WalletWasabi/WabiSabi/Backend/Rounds/Arena.cs
WalletWasabi/WabiSabi/Backend/Rounds/Arena.cs
@@ -71,7 +71,7 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
{
foreach (var round in Rounds.Where(x =>
x.Phase == Phase.InputRegistration
- && x.IsInputRegistrationEnded(Config.MaxInputCountByRound, Config.GetInputRegistrationTimeout(x)))
+ && x.IsInputRegistrationEnded(Config.MaxInputCountByRound))
.ToArray())
{
if (round.InputCount < Config.MinInputCountByRound)
@@ -107,7 +107,7 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
{
round.SetPhase(Phase.OutputRegistration);
}
- else if (round.ConnectionConfirmationStart + round.ConnectionConfirmationTimeout < DateTimeOffset.UtcNow)
+ else if (round.ConnectionConfirmationTimeFrame.HasExpired)
{
var alicesDidntConfirm = round.Alices.Where(x => !x.ConfirmedConnection).ToArray();
foreach (var alice in alicesDidntConfirm)
@@ -154,7 +154,7 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
var diff = aliceSum - bobSum;
var allReady = round.Alices.All(a => a.ReadyToSign);
- if (allReady || round.OutputRegistrationStart + round.OutputRegistrationTimeout < DateTimeOffset.UtcNow)
+ if (allReady || round.OutputRegistrationTimeFrame.HasExpired)
{
var coinjoin = round.Assert<ConstructionState>();
@@ -221,9 +221,9 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
round.LogInfo($"Successfully broadcast the CoinJoin: {coinjoin.GetHash()}.");
}
- else if (round.TransactionSigningStart + round.TransactionSigningTimeout < DateTimeOffset.UtcNow)
+ else if (round.TransactionSigningTimeFrame.HasExpired)
{
- throw new TimeoutException($"Round {round.Id}: Signing phase timed out after {round.TransactionSigningTimeout.TotalSeconds} seconds.");
+ throw new TimeoutException($"Round {round.Id}: Signing phase timed out after {round.TransactionSigningTimeFrame.Duration.TotalSeconds} seconds.");
}
}
catch (Exception ex)
@@ -311,7 +311,7 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
private void TimeoutAlices()
{
- foreach (var round in Rounds.Where(x => !x.IsInputRegistrationEnded(Config.MaxInputCountByRound, Config.GetInputRegistrationTimeout(x))).ToArray())
+ foreach (var round in Rounds.Where(x => !x.IsInputRegistrationEnded(Config.MaxInputCountByRound)).ToArray())
{
var removedAliceCount = round.Alices.RemoveAll(x => x.Deadline < DateTimeOffset.UtcNow);
if (removedAliceCount > 0)
@@ -348,9 +348,7 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.AliceAlreadyRegistered);
}
- if (round.IsInputRegistrationEnded(
- Config.MaxInputCountByRound,
- Config.GetInputRegistrationTimeout(round)))
+ if (round.IsInputRegistrationEnded(Config.MaxInputCountByRound))
{
throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.WrongPhase);
}
@@ -403,7 +401,7 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
var commitAmountCredentialResponse = await amountCredentialTask.ConfigureAwait(false);
var commitVsizeCredentialResponse = await vsizeCredentialTask.ConfigureAwait(false);
- alice.SetDeadlineRelativeTo(round.ConnectionConfirmationTimeout);
+ alice.SetDeadlineRelativeTo(round.ConnectionConfirmationTimeFrame.Duration);
round.Alices.Add(alice);
return new(alice.Id,
@@ -512,7 +510,7 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
{
var commitAmountZeroCredentialResponse = await amountZeroCredentialTask.ConfigureAwait(false);
var commitVsizeZeroCredentialResponse = await vsizeZeroCredentialTask.ConfigureAwait(false);
- alice.SetDeadlineRelativeTo(round.ConnectionConfirmationTimeout);
+ alice.SetDeadlineRelativeTo(round.ConnectionConfirmationTimeFrame.Duration);
return new(
commitAmountZeroCredentialResponse,
commitVsizeZeroCredentialResponse);

MODIFY
WalletWasabi/WabiSabi/Backend/Rounds/Round.cs
WalletWasabi/WabiSabi/Backend/Rounds/Round.cs
@@ -29,6 +29,11 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
VsizeCredentialIssuer = new(new(RoundParameters.Random), RoundParameters.Random, MaxVsizeCredentialValue);
AmountCredentialIssuerParameters = AmountCredentialIssuer.CredentialIssuerSecretKey.ComputeCredentialIssuerParameters();
VsizeCredentialIssuerParameters = VsizeCredentialIssuer.CredentialIssuerSecretKey.ComputeCredentialIssuerParameters();
+
+ InputRegistrationTimeFrame = TimeFrame.Create(IsBlameRound ? RoundParameters.BlameInputRegistrationTimeout : RoundParameters.StandardInputRegistrationTimeout).StartNow();
+ ConnectionConfirmationTimeFrame = TimeFrame.Create(RoundParameters.ConnectionConfirmationTimeout);
+ OutputRegistrationTimeFrame = TimeFrame.Create(RoundParameters.OutputRegistrationTimeout);
+ TransactionSigningTimeFrame = TimeFrame.Create(RoundParameters.TransactionSigningTimeout);
}
public uint256 Id => _id ??= CalculateHash();
@@ -51,16 +56,11 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
public bool IsBlameRound => RoundParameters.IsBlameRound;
public ISet<OutPoint> BlameWhitelist => RoundParameters.BlameWhitelist;
- public TimeSpan InputRegistrationTimeout => IsBlameRound ? RoundParameters.BlameInputRegistrationTimeout : RoundParameters.StandardInputRegistrationTimeout;
- public TimeSpan ConnectionConfirmationTimeout => RoundParameters.ConnectionConfirmationTimeout;
- public TimeSpan OutputRegistrationTimeout => RoundParameters.OutputRegistrationTimeout;
- public TimeSpan TransactionSigningTimeout => RoundParameters.TransactionSigningTimeout;
-
public Phase Phase { get; private set; } = Phase.InputRegistration;
- public DateTimeOffset InputRegistrationStart { get; } = DateTimeOffset.UtcNow;
- public DateTimeOffset ConnectionConfirmationStart { get; private set; }
- public DateTimeOffset OutputRegistrationStart { get; private set; }
- public DateTimeOffset TransactionSigningStart { get; private set; }
+ public TimeFrame InputRegistrationTimeFrame { get; internal set; }
+ public TimeFrame ConnectionConfirmationTimeFrame { get; private set; }
+ public TimeFrame OutputRegistrationTimeFrame { get; private set; }
+ public TimeFrame TransactionSigningTimeFrame { get; private set; }
public DateTimeOffset End { get; private set; }
public bool WasTransactionBroadcast { get; set; }
public int InitialInputVsizeAllocation { get; internal set; }
@@ -87,15 +87,15 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
if (phase == Phase.ConnectionConfirmation)
{
- ConnectionConfirmationStart = DateTimeOffset.UtcNow;
+ ConnectionConfirmationTimeFrame = ConnectionConfirmationTimeFrame.StartNow();
}
else if (phase == Phase.OutputRegistration)
{
- OutputRegistrationStart = DateTimeOffset.UtcNow;
+ OutputRegistrationTimeFrame = OutputRegistrationTimeFrame.StartNow();
}
else if (phase == Phase.TransactionSigning)
{
- TransactionSigningStart = DateTimeOffset.UtcNow;
+ TransactionSigningTimeFrame = TransactionSigningTimeFrame.StartNow();
}
else if (phase == Phase.Ended)
{
@@ -103,7 +103,7 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
}
}
- public bool IsInputRegistrationEnded(int maxInputCount, TimeSpan inputRegistrationTimeout)
+ public bool IsInputRegistrationEnded(int maxInputCount)
{
if (Phase > Phase.InputRegistration)
{
@@ -122,12 +122,7 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
return true;
}
- if (InputRegistrationStart + inputRegistrationTimeout < DateTimeOffset.UtcNow)
- {
- return true;
- }
-
- return false;
+ return InputRegistrationTimeFrame.HasExpired;
}
public ConstructionState AddInput(Coin coin)
@@ -141,11 +136,11 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
private uint256 CalculateHash()
=> RoundHasher.CalculateHash(
- InputRegistrationStart,
- InputRegistrationTimeout,
- ConnectionConfirmationTimeout,
- OutputRegistrationTimeout,
- TransactionSigningTimeout,
+ InputRegistrationTimeFrame.StartTime,
+ InputRegistrationTimeFrame.Duration,
+ ConnectionConfirmationTimeFrame.Duration,
+ OutputRegistrationTimeFrame.Duration,
+ TransactionSigningTimeFrame.Duration,
CoinjoinState.Parameters.AllowedInputAmounts,
CoinjoinState.Parameters.AllowedInputTypes,
CoinjoinState.Parameters.AllowedOutputAmounts,

ADD
WalletWasabi/WabiSabi/Backend/Rounds/TimeFrame.cs
+using System;
+
+namespace WalletWasabi.WabiSabi.Backend.Rounds
+{
+ public record TimeFrame
+ {
+ private TimeFrame(DateTimeOffset startTime, TimeSpan duration)
+ {
+ StartTime = startTime;
+ Duration = duration;
+ }
+
+ public static TimeFrame Create(TimeSpan duration) =>
+ new (DateTimeOffset.MinValue, duration);
+
+ public DateTimeOffset StartTime { get; init; }
+ public TimeSpan Duration { get; init; }
+ public DateTimeOffset EndTime => StartTime + Duration;
+ public bool HasStarted => StartTime > DateTimeOffset.MinValue && StartTime < DateTimeOffset.UtcNow;
+ public bool HasExpired => HasStarted && EndTime < DateTimeOffset.UtcNow;
+ public TimeFrame StartNow() => this with { StartTime = DateTimeOffset.UtcNow };
+ }
+}
\ No newline at end of file

MODIFY
WalletWasabi/WabiSabi/Models/RoundState.cs
WalletWasabi/WabiSabi/Models/RoundState.cs
@@ -39,11 +39,11 @@ namespace WalletWasabi.WabiSabi.Models
round.FeeRate,
round.Phase,
round.WasTransactionBroadcast,
- round.InputRegistrationStart,
- round.InputRegistrationTimeout,
- round.ConnectionConfirmationTimeout,
- round.OutputRegistrationTimeout,
- round.TransactionSigningTimeout,
+ round.InputRegistrationTimeFrame.StartTime,
+ round.InputRegistrationTimeFrame.Duration,
+ round.ConnectionConfirmationTimeFrame.Duration,
+ round.OutputRegistrationTimeFrame.Duration,
+ round.TransactionSigningTimeFrame.Duration,
round.MaxAmountCredentialValue,
round.MaxVsizeCredentialValue,
round.MaxVsizeAllocationPerAlice,

Simplify timeouts handling