public IActionResult ConnectionConfirmation([FromBody] ConnectionConfirmationRequest request) { var roundId = Global.StateMachine.RoundId; TumblerPhase phase = TumblerPhase.ConnectionConfirmation; try { if (Global.StateMachine.Phase != TumblerPhase.ConnectionConfirmation || !Global.StateMachine.AcceptRequest) { return(new ObjectResult(new FailureResponse { Message = "Wrong phase" })); } if (string.IsNullOrWhiteSpace(request.UniqueId)) { return(new BadRequestResult()); } Alice alice = Global.StateMachine.FindAlice(request.UniqueId, throwException: true); if (alice.State == AliceState.ConnectionConfirmed) { return(new ObjectResult(new ConnectionConfirmationResponse { RoundHash = Global.StateMachine.RoundHash })); } AssertPhase(roundId, phase); alice.State = AliceState.ConnectionConfirmed; try { return(new ObjectResult(new ConnectionConfirmationResponse { RoundHash = Global.StateMachine.RoundHash })); } finally { if (Global.StateMachine.Alices.All(x => x.State == AliceState.ConnectionConfirmed)) { Global.StateMachine.UpdatePhase(TumblerPhase.OutputRegistration); } } } catch (Exception ex) { return(new ObjectResult(new FailureResponse { Message = ex.Message })); } }
public async Task <ConnectionConfirmationResponse> ConfirmConnectionAsync(ConnectionConfirmationRequest request, CancellationToken cancellationToken) { try { return(await ConfirmConnectionCoreAsync(request, cancellationToken).ConfigureAwait(false)); } catch (Exception ex) when(IsUserCheating(ex)) { var round = GetRound(request.RoundId); var alice = GetAlice(request.AliceId, round); Prison.Ban(alice.Coin.Outpoint, round.Id); throw; } }
public async Task <ConnectionConfirmationResponse> ConfirmConnectionAsync(ConnectionConfirmationRequest request, CancellationToken cancellationToken) { return(await IdempotencyRequestCache.GetCachedResponseAsync(request, action : (request, token) => Arena.ConfirmConnectionAsync(request, token), cancellationToken)); }
public Task <ConnectionConfirmationResponse> ConfirmConnectionAsync(ConnectionConfirmationRequest request, CancellationToken cancellableToken) { return(RequestHandler.ConfirmConnectionAsync(request, cancellableToken)); }
public Task <ConnectionConfirmationResponse> ConfirmConnectionAsync(ConnectionConfirmationRequest request, CancellationToken cancellationToken) => SendAndReceiveAsync <ConnectionConfirmationRequest, ConnectionConfirmationResponse>(RemoteAction.ConfirmConnection, request, cancellationToken);
public async Task <ConnectionConfirmationResponse> ConfirmConnectionAsync(ConnectionConfirmationRequest request, CancellationToken cancellationToken) { Round round; Alice alice; var realAmountCredentialRequests = request.RealAmountCredentialRequests; var realVsizeCredentialRequests = request.RealVsizeCredentialRequests; using (await AsyncLock.LockAsync(cancellationToken).ConfigureAwait(false)) { round = GetRound(request.RoundId, Phase.InputRegistration, Phase.ConnectionConfirmation); alice = GetAlice(request.AliceId, round); if (alice.ConfirmedConnection) { Prison.Ban(alice, round.Id); throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.AliceAlreadyConfirmedConnection, $"Round ({request.RoundId}): Alice ({request.AliceId}) already confirmed connection."); } if (realVsizeCredentialRequests.Delta != alice.CalculateRemainingVsizeCredentials(round.MaxVsizeAllocationPerAlice)) { throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.IncorrectRequestedVsizeCredentials, $"Round ({request.RoundId}): Incorrect requested vsize credentials."); } if (realAmountCredentialRequests.Delta != alice.CalculateRemainingAmountCredentials(round.FeeRate)) { throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.IncorrectRequestedAmountCredentials, $"Round ({request.RoundId}): Incorrect requested amount credentials."); } } var amountZeroCredentialTask = round.AmountCredentialIssuer.HandleRequestAsync(request.ZeroAmountCredentialRequests, cancellationToken); var vsizeZeroCredentialTask = round.VsizeCredentialIssuer.HandleRequestAsync(request.ZeroVsizeCredentialRequests, cancellationToken); Task <CredentialsResponse>?amountRealCredentialTask = null; Task <CredentialsResponse>?vsizeRealCredentialTask = null; if (round.Phase is Phase.ConnectionConfirmation) { amountRealCredentialTask = round.AmountCredentialIssuer.HandleRequestAsync(realAmountCredentialRequests, cancellationToken); vsizeRealCredentialTask = round.VsizeCredentialIssuer.HandleRequestAsync(realVsizeCredentialRequests, cancellationToken); } using (await AsyncLock.LockAsync(cancellationToken).ConfigureAwait(false)) { alice = GetAlice(request.AliceId, round); switch (round.Phase) { case Phase.InputRegistration: { var commitAmountZeroCredentialResponse = await amountZeroCredentialTask.ConfigureAwait(false); var commitVsizeZeroCredentialResponse = await vsizeZeroCredentialTask.ConfigureAwait(false); alice.SetDeadlineRelativeTo(round.ConnectionConfirmationTimeFrame.Duration); return(new( commitAmountZeroCredentialResponse, commitVsizeZeroCredentialResponse)); } case Phase.ConnectionConfirmation: { // If the phase was InputRegistration before then we did not pre-calculate real credentials. amountRealCredentialTask ??= round.AmountCredentialIssuer.HandleRequestAsync(realAmountCredentialRequests, cancellationToken); vsizeRealCredentialTask ??= round.VsizeCredentialIssuer.HandleRequestAsync(realVsizeCredentialRequests, cancellationToken); ConnectionConfirmationResponse response = new( await amountZeroCredentialTask.ConfigureAwait(false), await vsizeZeroCredentialTask.ConfigureAwait(false), await amountRealCredentialTask.ConfigureAwait(false), await vsizeRealCredentialTask.ConfigureAwait(false)); // Update the CoinJoin state, adding the confirmed input. round.CoinjoinState = round.Assert <ConstructionState>().AddInput(alice.Coin); alice.ConfirmedConnection = true; return(response); } default: throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.WrongPhase, $"Round ({request.RoundId}): Wrong phase ({round.Phase})."); } } }
public Task <ConnectionConfirmationResponse> ConfirmConnectionAsync(ConnectionConfirmationRequest request, CancellationToken cancellationToken) => arena.ConfirmConnectionAsync(request);
public async Task <ConnectionConfirmationResponse> PostConnectionConfirmationAsync(ConnectionConfirmationRequest request, CancellationToken cancel) { using (await _asyncLock.LockAsync()) { string requestJsonString = JsonConvert.SerializeObject(request); var content = new StringContent( requestJsonString, Encoding.UTF8, "application/json"); HttpResponseMessage response = await PostAsync("connection-confirmation", content, cancel); if (!response.IsSuccessStatusCode) { throw new HttpRequestException(response.StatusCode.ToString()); } string responseString = await response.Content.ReadAsStringAsync(); AssertSuccess(responseString); return(JsonConvert.DeserializeObject <ConnectionConfirmationResponse>(responseString)); } }