Fix backend micro unresponsiveness
MODIFY
WalletWasabi.Backend/Controllers/BatchController.cs
WalletWasabi.Backend/Controllers/BatchController.cs
@@ -88,7 +88,7 @@ namespace WalletWasabi.Backend.Controllers
response.ExchangeRates = await OffchainController.GetExchangeRatesCollectionAsync();
- response.UnconfirmedCoinJoins = await ChaumianCoinJoinController.GetUnconfirmedCoinJoinCollectionAsync();
+ response.UnconfirmedCoinJoins = ChaumianCoinJoinController.GetUnconfirmedCoinJoinCollection();
return Ok(response);
}

MODIFY
WalletWasabi.Backend/Controllers/ChaumianCoinJoinController.cs
WalletWasabi.Backend/Controllers/ChaumianCoinJoinController.cs
@@ -718,17 +718,13 @@ namespace WalletWasabi.Backend.Controllers
/// <response code="200">An array of transaction Ids</response>
[HttpGet("unconfirmed-coinjoins")]
[ProducesResponseType(200)]
- public async Task<IActionResult> GetUnconfirmedCoinjoinsAsync()
+ public IActionResult GetUnconfirmedCoinjoins()
{
- IEnumerable<string> unconfirmedCoinJoinString = (await GetUnconfirmedCoinJoinCollectionAsync()).Select(x => x.ToString());
+ IEnumerable<string> unconfirmedCoinJoinString = GetUnconfirmedCoinJoinCollection().Select(x => x.ToString());
return Ok(unconfirmedCoinJoinString);
}
- internal async Task<IEnumerable<uint256>> GetUnconfirmedCoinJoinCollectionAsync()
- {
- var unconfirmedCoinJoins = await Global.Coordinator.GetUnconfirmedCoinJoinsAsync();
- return unconfirmedCoinJoins;
- }
+ internal IEnumerable<uint256> GetUnconfirmedCoinJoinCollection() => Global.Coordinator.GetUnconfirmedCoinJoins();
private Guid GetGuidOrFailureResponse(string uniqueId, out IActionResult returnFailureResponse)
{

MODIFY
WalletWasabi/CoinJoin/Coordinator/Coordinator.cs
WalletWasabi/CoinJoin/Coordinator/Coordinator.cs
@@ -33,9 +33,6 @@ namespace WalletWasabi.CoinJoin.Coordinator
Rounds = new List<CoordinatorRound>();
RoundsListLock = new AsyncLock();
- CoinJoins = new List<uint256>();
- UnconfirmedCoinJoins = new List<uint256>();
- CoinJoinsLock = new AsyncLock();
LastSuccessfulCoinJoinTime = DateTimeOffset.UtcNow;
Directory.CreateDirectory(FolderPath);
@@ -137,11 +134,12 @@ namespace WalletWasabi.CoinJoin.Coordinator
private List<CoordinatorRound> Rounds { get; }
private AsyncLock RoundsListLock { get; }
- private List<uint256> CoinJoins { get; }
+ private List<uint256> CoinJoins { get; } = new List<uint256>();
public string CoinJoinsFilePath => Path.Combine(FolderPath, $"CoinJoins{Network}.txt");
- private AsyncLock CoinJoinsLock { get; }
+ private AsyncLock CoinJoinsLock { get; } = new AsyncLock();
- private List<uint256> UnconfirmedCoinJoins { get; }
+ private List<uint256> UnconfirmedCoinJoins { get; } = new List<uint256>();
+ private object UnconfirmedCoinJoinsLock { get; } = new object();
public IRPCClient RpcClient { get; }
@@ -183,7 +181,10 @@ namespace WalletWasabi.CoinJoin.Coordinator
// ban all the outputs of the transaction
tx.PrecomputeHash(false, true);
- UnconfirmedCoinJoins.Remove(tx.GetHash()); // Locked outside.
+ lock (UnconfirmedCoinJoinsLock)
+ {
+ UnconfirmedCoinJoins.Remove(tx.GetHash());
+ }
if (RoundConfig.DosSeverity <= 1)
{
@@ -293,17 +294,20 @@ namespace WalletWasabi.CoinJoin.Coordinator
}
using (await CoinJoinsLock.LockAsync().ConfigureAwait(false))
+ {
+ uint256 coinJoinHash = round.CoinJoin.GetHash();
+ lock (UnconfirmedCoinJoinsLock)
{
if (mempoolHashes is { })
{
- var fallOuts = UnconfirmedCoinJoins.Where(x => !mempoolHashes.Contains(x));
+ var fallOuts = UnconfirmedCoinJoins.Where(x => !mempoolHashes.Contains(x)).ToHashSet();
CoinJoins.RemoveAll(x => fallOuts.Contains(x));
UnconfirmedCoinJoins.RemoveAll(x => fallOuts.Contains(x));
}
- uint256 coinJoinHash = round.CoinJoin.GetHash();
CoinJoins.Add(coinJoinHash);
UnconfirmedCoinJoins.Add(coinJoinHash);
+ }
LastSuccessfulCoinJoinTime = DateTimeOffset.UtcNow;
await File.AppendAllLinesAsync(CoinJoinsFilePath, new[] { coinJoinHash.ToString() }).ConfigureAwait(false);
@@ -446,22 +450,14 @@ namespace WalletWasabi.CoinJoin.Coordinator
}
}
- public async Task<bool> ContainsUnconfirmedCoinJoinAsync(uint256 hash)
- {
- using (await CoinJoinsLock.LockAsync().ConfigureAwait(false))
- {
- return UnconfirmedCoinJoins.Contains(hash);
- }
- }
-
public int GetCoinJoinCount()
{
return CoinJoins.Count;
}
- public async Task<IEnumerable<uint256>> GetUnconfirmedCoinJoinsAsync()
+ public IEnumerable<uint256> GetUnconfirmedCoinJoins()
{
- using (await CoinJoinsLock.LockAsync())
+ lock (UnconfirmedCoinJoinsLock)
{
return UnconfirmedCoinJoins.ToArray();
}

Fix backend micro unresponsiveness