Implement anonset adjusting after signing failure
MODIFY
WalletWasabi.Tests/RegTests.cs
WalletWasabi.Tests/RegTests.cs
@@ -2488,6 +2488,9 @@ namespace WalletWasabi.Tests
var request = aliceClients[i];
var aliceClient = await request;
+ aliceClient.Requesters = new[] { user.requester };
+ aliceClient.OutputScriptHashes = new[] { user.activeOutputAddress };
+
if (roundId == 0)
{
roundId = aliceClient.RoundId;

MODIFY
WalletWasabi/Models/ChaumianCoinJoin/CcjRound.cs
WalletWasabi/Models/ChaumianCoinJoin/CcjRound.cs
@@ -823,7 +823,7 @@ namespace WalletWasabi.Models.ChaumianCoinJoin
return Bobs.Count;
}
}
- return Alices.Count;
+ return Bobs.Count;
}
public IEnumerable<Alice> GetAlicesBy(AliceState state)
@@ -944,7 +944,9 @@ namespace WalletWasabi.Models.ChaumianCoinJoin
}
}
- public void UpdateAnonymitySet(int anonymitySet)
+ public void UpdateAnonymitySet(int anonymitySet, bool syncLock = true)
+ {
+ if (syncLock)
{
using (RoundSynchronizerLock.Lock())
{
@@ -954,6 +956,15 @@ namespace WalletWasabi.Models.ChaumianCoinJoin
}
AnonymitySet = anonymitySet;
}
+ }
+ else
+ {
+ if ((Phase != CcjRoundPhase.InputRegistration && Phase != CcjRoundPhase.ConnectionConfirmation) || Status != CcjRoundStatus.Running)
+ {
+ throw new InvalidOperationException($"Updating anonymity set is not allowed in {Phase.ToString()} phase.");
+ }
+ AnonymitySet = anonymitySet;
+ }
Logger.LogInfo<CcjRound>($"Round ({RoundId}): {nameof(AnonymitySet)} updated: {AnonymitySet}.");
}

MODIFY
WalletWasabi/Services/CcjCoordinator.cs
WalletWasabi/Services/CcjCoordinator.cs
@@ -235,6 +235,25 @@ namespace WalletWasabi.Services
{
IEnumerable<Alice> alicesDidntSign = round.GetAlicesByNot(AliceState.SignedCoinJoin, syncLock: false);
+ CcjRound nextRound = GetCurrentInputRegisterableRoundOrDefault(syncLock: false);
+
+ if (nextRound != null)
+ {
+ int nextRoundAlicesCount = nextRound.CountAlices(syncLock: false);
+ var newAnonymitySet = Math.Max(nextRound.AnonymitySet - alicesDidntSign.Count(), nextRoundAlicesCount);
+
+ if (nextRound.AnonymitySet != newAnonymitySet)
+ {
+ nextRound.UpdateAnonymitySet(newAnonymitySet, syncLock: false);
+
+ if (nextRoundAlicesCount >= nextRound.AnonymitySet)
+ {
+ // Progress to the next phase, which will be OutputRegistration
+ await nextRound.ExecuteNextPhaseAsync(CcjRoundPhase.ConnectionConfirmation);
+ }
+ }
+ }
+
foreach (Alice alice in alicesDidntSign) // Because the event sometimes is raised from inside the lock.
{
// If its from any coinjoin, then don't ban.

Implement anonset adjusting after signing failure