Fix edge case when there is not remaining time
MODIFY
WalletWasabi/Extensions/TimeSpanExtensions.cs
WalletWasabi/Extensions/TimeSpanExtensions.cs
@@ -6,13 +6,16 @@ namespace System
{
public static class TimeSpanExtensions
{
- public static ImmutableList<DateTimeOffset> Sample(this TimeSpan timeFrame, int numberOfEvents)
+ public static ImmutableList<DateTimeOffset> SamplePoisson(this TimeSpan timeFrame, int numberOfEvents)
{
var startTime = DateTimeOffset.UtcNow;
using var random = new SecureRandom();
+ TimeSpan Sample(int milliseconds) =>
+ milliseconds <= 0 ? TimeSpan.Zero : TimeSpan.FromMilliseconds(random.GetInt(0, milliseconds));
+
return Enumerable
.Range(0, numberOfEvents)
- .Select(_ => startTime + (0.8 * TimeSpan.FromMilliseconds(random.GetInt(0, (int)timeFrame.TotalMilliseconds))))
+ .Select(_ => startTime + (0.8 * Sample((int)timeFrame.TotalMilliseconds)))
.OrderBy(t => t)
.ToImmutableList();
}

MODIFY
WalletWasabi/WabiSabi/Client/CoinJoinClient.cs
WalletWasabi/WabiSabi/Client/CoinJoinClient.cs
@@ -192,7 +192,7 @@ namespace WalletWasabi.WabiSabi.Client
// Gets the list of scheduled dates/time in the remaining available time frame when each alice has to be registered.
var remainingTimeForRegistration = roundState.InputRegistrationEnd - DateTimeOffset.UtcNow;
- var scheduledDates = remainingTimeForRegistration.Sample(smartCoins.Count());
+ var scheduledDates = remainingTimeForRegistration.SamplePoisson(smartCoins.Count());
// Creates scheduled tasks (tasks that wait until the specified date/time and then perform the real registration)
var aliceClients = smartCoins.Zip(scheduledDates, (coin, date) => RegisterInputAsync(coin, cancellationToken).RunAsScheduledAsync(date, cancellationToken)).ToImmutableArray();
@@ -242,7 +242,7 @@ namespace WalletWasabi.WabiSabi.Client
// Gets the list of scheduled dates/time in the remaining available time frame when each alice has to sign.
var transactionSigningTimeFrame = roundState.TransactionSigningTimeout - RoundStatusUpdater.Period;
- var scheduledDates = transactionSigningTimeFrame.Sample(aliceClients.Count());
+ var scheduledDates = transactionSigningTimeFrame.SamplePoisson(aliceClients.Count());
// Creates scheduled tasks (tasks that wait until the specified date/time and then perform the real registration)
var signingRequests = aliceClients.Zip(scheduledDates, (alice, date) => SignTransactionAsync(alice, cancellationToken).RunAsScheduledAsync(date, cancellationToken)).ToImmutableArray();

Fix edge case when there is not remaining time