예제 #1
0
        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
                }));
            }
        }
예제 #2
0
    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;
        }
    }
예제 #3
0
 public async Task <ConnectionConfirmationResponse> ConfirmConnectionAsync(ConnectionConfirmationRequest request, CancellationToken cancellationToken)
 {
     return(await IdempotencyRequestCache.GetCachedResponseAsync(request, action : (request, token) => Arena.ConfirmConnectionAsync(request, token), cancellationToken));
 }
예제 #4
0
 public Task <ConnectionConfirmationResponse> ConfirmConnectionAsync(ConnectionConfirmationRequest request, CancellationToken cancellableToken)
 {
     return(RequestHandler.ConfirmConnectionAsync(request, cancellableToken));
 }
예제 #5
0
 public Task <ConnectionConfirmationResponse> ConfirmConnectionAsync(ConnectionConfirmationRequest request, CancellationToken cancellationToken) =>
 SendAndReceiveAsync <ConnectionConfirmationRequest, ConnectionConfirmationResponse>(RemoteAction.ConfirmConnection, request, cancellationToken);
예제 #6
0
        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);
예제 #8
0
        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));
            }
        }