Make status requests concurrency safe
Since status requests access internal mutable structures of `Arena` they
need to be protected by the async lock to avoid reading inconsistent
states.
MODIFY
WalletWasabi.Backend/Controllers/WabiSabiController.cs
WalletWasabi.Backend/Controllers/WabiSabiController.cs
@@ -21,6 +21,12 @@ namespace WalletWasabi.Backend.Controllers
private ArenaRequestHandler RequestHandler { get; }
+ [HttpGet("status")]
+ public Task<RoundState[]> GetStatusAsync(CancellationToken cancellationToken)
+ {
+ return RequestHandler.GetStatusAsync(cancellationToken);
+ }
+
[HttpPost("connection-confirmation")]
[Idempotent]
public Task<ConnectionConfirmationResponse> ConfirmConnectionAsync(ConnectionConfirmationRequest request, CancellationToken cancellableToken)
@@ -61,12 +67,6 @@ namespace WalletWasabi.Backend.Controllers
return RequestHandler.SignTransactionAsync(request, cancellableToken);
}
- [HttpGet("status")]
- public Task<RoundState[]> GetStatusAsync(CancellationToken cancellableToken)
- {
- return Task.FromResult(RequestHandler.Arena.Rounds.Select(x => RoundState.FromRound(x)).ToArray());
- }
-
[HttpPost("ready-to-sign")]
public Task ReadyToSign(ReadyToSignRequestRequest request, CancellationToken cancellableToken)
{

MODIFY
WalletWasabi/WabiSabi/Backend/PostRequests/ArenaRequestHandler.cs
WalletWasabi/WabiSabi/Backend/PostRequests/ArenaRequestHandler.cs
@@ -93,6 +93,15 @@ namespace WalletWasabi.WabiSabi.Backend.PostRequests
}
}
+ public async Task<RoundState[]> GetStatusAsync(CancellationToken cancellationToken)
+ {
+ DisposeGuard();
+ using (RunningTasks.RememberWith(RunningRequests))
+ {
+ return await Arena.GetStatusAsync(cancellationToken).ConfigureAwait(false);
+ }
+ }
+
public async ValueTask DisposeAsync()
{
lock (DisposeStartedLock)

MODIFY
WalletWasabi/WabiSabi/Backend/Rounds/Arena.cs
WalletWasabi/WabiSabi/Backend/Rounds/Arena.cs
@@ -247,6 +247,14 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
}
}
+ public async Task<RoundState[]> GetStatusAsync(CancellationToken cancellationToken)
+ {
+ using (await AsyncLock.LockAsync(cancellationToken).ConfigureAwait(false))
+ {
+ return Rounds.Select(x => RoundState.FromRound(x)).ToArray();
+ }
+ }
+
public async Task<InputRegistrationResponse> RegisterInputAsync(InputRegistrationRequest request)
{
var coin = await InputRegistrationHandler.OutpointToCoinAsync(request, Prison, Rpc, Config).ConfigureAwait(false);

Make status requests concurrency safe

Since status requests access internal mutable structures of `Arena` they
need to be protected by the async lock to avoid reading inconsistent
states.