Add possibility of disconnection in input registration phase
MODIFY
HiddenWallet.ChaumianTumbler/Controllers/TumblerController.cs
HiddenWallet.ChaumianTumbler/Controllers/TumblerController.cs
@@ -236,6 +236,35 @@ namespace HiddenWallet.ChaumianTumbler.Controllers
}
}
+ [Route("disconnection")]
+ [HttpPost]
+ public async Task<IActionResult> DisconnectionAsync([FromBody]DisconnectionRequest request)
+ {
+ try
+ {
+ if (string.IsNullOrWhiteSpace(request.UniqueId)) return new BadRequestResult();
+
+ using (await InputRegistrationLock.LockAsync())
+ {
+ if (Global.StateMachine.Phase != TumblerPhase.InputRegistration || !Global.StateMachine.AcceptRequest)
+ {
+ return new ObjectResult(new FailureResponse { Message = "Wrong phase", Details = "" });
+ }
+
+ if(Global.StateMachine.TryRemoveAlice(request.UniqueId))
+ {
+ await Global.StateMachine.BroadcastPeerRegisteredAsync();
+ }
+ }
+
+ return new ObjectResult(new SuccessResponse());
+ }
+ catch (Exception ex)
+ {
+ return new ObjectResult(new FailureResponse { Message = ex.Message, Details = ex.ToString() });
+ }
+ }
+
[Route("connection-confirmation")]
[HttpPost]
public IActionResult ConnectionConfirmation([FromBody]ConnectionConfirmationRequest request)

MODIFY
HiddenWallet.ChaumianTumbler/TumblerStateMachine.cs
HiddenWallet.ChaumianTumbler/TumblerStateMachine.cs
@@ -310,7 +310,10 @@ namespace HiddenWallet.ChaumianTumbler
}
}
+ private object _aliceLock = new object();
public Alice FindAlice(string uniqueId, bool throwException)
+ {
+ lock (_aliceLock)
{
Alice alice = Alices.FirstOrDefault(x => x.UniqueId == new Guid(uniqueId));
if (alice == default(Alice))
@@ -323,6 +326,16 @@ namespace HiddenWallet.ChaumianTumbler
return alice;
}
+ }
+
+ public bool TryRemoveAlice(string uniqueId)
+ {
+ lock (_aliceLock)
+ {
+ Alice alice = Alices.FirstOrDefault(x => x.UniqueId == new Guid(uniqueId));
+ return Alices.TryRemove(alice);
+ }
+ }
#region IDisposable Support
private bool _disposedValue = false; // To detect redundant calls

MODIFY
HiddenWallet.FullSpvWallet/ChaumianCoinJoin/CoinJoinService.cs
HiddenWallet.FullSpvWallet/ChaumianCoinJoin/CoinJoinService.cs
@@ -57,6 +57,7 @@ namespace HiddenWallet.FullSpvWallet.ChaumianCoinJoin
{
CompletedLastPhase = true;
TumblingInProcess = false;
+ UniqueAliceId = null;
TumblerConnection = null;
CoinJoin = null;
TumblingException = null;
@@ -375,6 +376,7 @@ namespace HiddenWallet.FullSpvWallet.ChaumianCoinJoin
};
await TumblerClient.PostSignatureAsync(sigRequest, cancel);
TumblingInProcess = false;
+ UniqueAliceId = null;
}
else throw new NotSupportedException("This should never happen");
}
@@ -382,6 +384,7 @@ namespace HiddenWallet.FullSpvWallet.ChaumianCoinJoin
{
// if an exception happened don't tumbler anymore in this round
TumblingInProcess = false;
+ UniqueAliceId = null;
TumblingException = ex;
throw;
}
@@ -392,6 +395,18 @@ namespace HiddenWallet.FullSpvWallet.ChaumianCoinJoin
}
}
+ /// <summary>
+ /// throws if couldn't cancel
+ /// </summary>
+ public async Task CancelMixAsync(CancellationToken cancel)
+ {
+ if (UniqueAliceId != null)
+ {
+ var request = new DisconnectionRequest { UniqueId = UniqueAliceId };
+ await TumblerClient.PostDisconnectionAsync(request, cancel);
+ }
+ }
+
#endregion
#region Disposing
@@ -400,6 +415,16 @@ namespace HiddenWallet.FullSpvWallet.ChaumianCoinJoin
{
try
{
+
+ try
+ {
+ await CancelMixAsync(CancellationToken.None);
+ }
+ catch
+ {
+
+ }
+
if (TumblerConnection != null)
{
try
@@ -413,6 +438,7 @@ namespace HiddenWallet.FullSpvWallet.ChaumianCoinJoin
await TumblerConnection?.DisposeAsync();
TumblerConnection = null;
}
+
TumblerClient?.Dispose();
}
catch (Exception)

MODIFY
HiddenWallet/ChaumianCoinJoin/ChaumianTumblerClient.cs
HiddenWallet/ChaumianCoinJoin/ChaumianTumblerClient.cs
@@ -103,6 +103,25 @@ namespace HiddenWallet.ChaumianCoinJoin
}
}
+ public async Task PostDisconnectionAsync(DisconnectionRequest request, CancellationToken cancel)
+ {
+ using (await _asyncLock.LockAsync())
+ {
+ string requestJsonString = JsonConvert.SerializeObject(request);
+ var content = new StringContent(
+ requestJsonString,
+ Encoding.UTF8,
+ "application/json");
+
+ HttpResponseMessage response =
+ await HttpClient.PostAsync("disconnection", content, cancel);
+
+ if (!response.IsSuccessStatusCode) throw new HttpRequestException(response.StatusCode.ToString());
+ string responseString = await response.Content.ReadAsStringAsync();
+ AssertSuccess(responseString);
+ }
+ }
+
public async Task PostOutputAsync(OutputRequest request, CancellationToken cancel)
{
using (await _asyncLock.LockAsync())

Add possibility of disconnection in input registration phase