Schedule input registrations
MODIFY
WalletWasabi.Tests/UnitTests/WabiSabi/Integration/WabiSabiHttpApiIntegrationTests.cs
WalletWasabi.Tests/UnitTests/WabiSabi/Integration/WabiSabiHttpApiIntegrationTests.cs
@@ -108,7 +108,11 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Integration
// Instruct the coordinator DI container to use these two scoped
// services to build everything (WabiSabi controller, arena, etc)
services.AddScoped<IRPCClient>(s => rpc);
- services.AddScoped<WabiSabiConfig>(s => new WabiSabiConfig { MaxInputCountByRound = inputCount });
+ services.AddScoped(s => new WabiSabiConfig
+ {
+ MaxInputCountByRound = inputCount,
+ StandardInputRegistrationTimeout = TimeSpan.FromSeconds(10)
+ });
});
}).CreateClient();
@@ -200,6 +204,8 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Integration
services.AddScoped<WabiSabiConfig>(s => new WabiSabiConfig
{
MaxInputCountByRound = 2 * inputCount,
+ StandardInputRegistrationTimeout = TimeSpan.FromSeconds(20),
+ BlameInputRegistrationTimeout = TimeSpan.FromSeconds(20),
TransactionSigningTimeout = TimeSpan.FromSeconds(5 * inputCount),
});
});
@@ -284,6 +290,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Integration
{
MaxRegistrableAmount = Money.Coins(500m),
MaxInputCountByRound = ExpectedInputNumber,
+ StandardInputRegistrationTimeout = TimeSpan.FromSeconds(10 * ExpectedInputNumber),
ConnectionConfirmationTimeout = TimeSpan.FromSeconds(20 * ExpectedInputNumber),
OutputRegistrationTimeout = TimeSpan.FromSeconds(20 * ExpectedInputNumber),
});
@@ -296,7 +303,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Integration
.Returns(new HttpClientWrapper(app.CreateClient()));
// Total test timeout.
- using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(20 * ExpectedInputNumber));
+ using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(40 * ExpectedInputNumber));
var participants = Enumerable
.Range(0, NumberOfParticipants)

MODIFY
WalletWasabi/WabiSabi/Client/CoinJoinClient.cs
WalletWasabi/WabiSabi/Client/CoinJoinClient.cs
@@ -48,6 +48,7 @@ namespace WalletWasabi.WabiSabi.Client
public Kitchen Kitchen { get; }
public KeyManager Keymanager { get; }
private RoundStateUpdater RoundStatusUpdater { get; }
+ private Random Random { get; } = new Random();
public bool InCriticalCoinJoinState
{
@@ -162,7 +163,7 @@ namespace WalletWasabi.WabiSabi.Client
private async Task<ImmutableArray<AliceClient>> CreateRegisterAndConfirmCoinsAsync(IEnumerable<SmartCoin> smartCoins, RoundState roundState, CancellationToken cancellationToken)
{
- async Task<AliceClient?> RegisterInputTask(SmartCoin coin)
+ async Task<AliceClient?> RegisterInputTask(SmartCoin coin, DateTimeOffset when)
{
try
{
@@ -185,15 +186,22 @@ namespace WalletWasabi.WabiSabi.Client
var identificationMasterKey = Slip21Node.FromSeed(masterKey.ToBytes());
var identificationKey = identificationMasterKey.DeriveChild("SLIP-0019").DeriveChild("Ownership identification key").Key;
+ var timeToWait = when - DateTimeOffset.UtcNow;
+ var fixedTimeToWait = timeToWait < TimeSpan.Zero ? TimeSpan.Zero : timeToWait;
+ await Task.Delay(fixedTimeToWait, cancellationToken).ConfigureAwait(false);
return await AliceClient.CreateRegisterAndConfirmInputAsync(roundState, aliceArenaClient, coin, secret, identificationKey, RoundStatusUpdater, cancellationToken).ConfigureAwait(false);
}
- catch (HttpRequestException)
+ catch (HttpRequestException e)
{
return null;
}
}
- var aliceClients = smartCoins.Select(RegisterInputTask).ToImmutableArray();
+ var remainingTimeForRegistration = roundState.InputRegistrationStart + roundState.InputRegistrationTimeout - DateTimeOffset.UtcNow;
+ var registrationSchedule = CreateSchedule(DateTimeOffset.UtcNow, remainingTimeForRegistration, smartCoins.Count());
+ var aliceClients = smartCoins.Zip(registrationSchedule, (s, t) => (SmartCoin: s, When: t))
+ .Select(x => RegisterInputTask(x.SmartCoin, x.When))
+ .ToImmutableArray();
await Task.WhenAll(aliceClients).ConfigureAwait(false);
return aliceClients
@@ -275,5 +283,12 @@ namespace WalletWasabi.WabiSabi.Client
.Take(MaxInputsRegistrableByWallet)
.ToShuffled()
.ToImmutableList();
+
+ private ImmutableList<DateTimeOffset> CreateSchedule(DateTimeOffset startTime, TimeSpan timeFrame, int numberOfEvents) =>
+ Enumerable
+ .Range(0, numberOfEvents)
+ .Select(_ => startTime.Add(0.8 * Random.NextDouble() * timeFrame))
+ .OrderBy(t => t)
+ .ToImmutableList();
}
}

Schedule input registrations