public async Task <IActionResult> PostConfirmationAsync([FromQuery, Required] string uniqueId, [FromQuery, Required] long roundId) { if (roundId < 0 || !ModelState.IsValid) { return(BadRequest()); } (CoordinatorRound round, Alice alice) = GetRunningRoundAndAliceOrFailureResponse(roundId, uniqueId, RoundPhase.ConnectionConfirmation, out IActionResult returnFailureResponse); if (returnFailureResponse != null) { return(returnFailureResponse); } RoundPhase phase = round.Phase; // Start building the response. var resp = new ConnectionConfirmationResponse { CurrentPhase = phase }; switch (phase) { case RoundPhase.InputRegistration: { round.StartAliceTimeout(alice.UniqueId); break; } case RoundPhase.ConnectionConfirmation: { alice.State = AliceState.ConnectionConfirmed; int takeBlindCount = round.EstimateBestMixingLevel(alice); alice.BlindedOutputScripts = alice.BlindedOutputScripts.Take(takeBlindCount).ToArray(); alice.BlindedOutputSignatures = alice.BlindedOutputSignatures.Take(takeBlindCount).ToArray(); resp.BlindedOutputSignatures = alice.BlindedOutputSignatures; // Do not give back more mixing levels than we'll use. // Progress round if needed. if (round.AllAlices(AliceState.ConnectionConfirmed)) { await round.ProgressToOutputRegistrationOrFailAsync(); } break; } default: { TryLogLateRequest(roundId, RoundPhase.ConnectionConfirmation); return(Gone($"Participation can be only confirmed from InputRegistration or ConnectionConfirmation phase. Current phase: {phase}.")); } } return(Ok(resp)); }
public async Task <(RoundPhase currentPhase, IEnumerable <ActiveOutput> activeOutputs)> PostConfirmationAsync() { using HttpResponseMessage response = await TorClient.SendAsync(HttpMethod.Post, $"/api/v{Helpers.Constants.BackendMajorVersion}/btc/chaumiancoinjoin/confirmation?uniqueId={UniqueId}&roundId={RoundId}").ConfigureAwait(false); if (response.StatusCode != HttpStatusCode.OK) { await response.ThrowRequestExceptionFromContentAsync().ConfigureAwait(false); } ConnectionConfirmationResponse resp = await response.Content.ReadAsJsonAsync <ConnectionConfirmationResponse>().ConfigureAwait(false); Logger.LogInfo($"Round ({RoundId}), Alice ({UniqueId}): Confirmed connection. Phase: {resp.CurrentPhase}."); var activeOutputs = new List <ActiveOutput>(); if (resp.BlindedOutputSignatures != null && resp.BlindedOutputSignatures.Any()) { var unblindedSignatures = new List <UnblindedSignature>(); var blindedSignatures = resp.BlindedOutputSignatures.ToArray(); for (int i = 0; i < blindedSignatures.Length; i++) { uint256 blindedSignature = blindedSignatures[i]; Requester requester = Requesters[i]; UnblindedSignature unblindedSignature = requester.UnblindSignature(blindedSignature); var address = RegisteredAddresses[i]; uint256 outputScriptHash = new uint256(Hashes.SHA256(address.ScriptPubKey.ToBytes())); PubKey signerPubKey = SchnorrPubKeys[i].SignerPubKey; if (!VerifySignature(outputScriptHash, unblindedSignature, signerPubKey)) { throw new NotSupportedException($"Coordinator did not sign the blinded output properly for level: {i}."); } unblindedSignatures.Add(unblindedSignature); } for (int i = 0; i < Math.Min(unblindedSignatures.Count, RegisteredAddresses.Length); i++) { var sig = unblindedSignatures[i]; var addr = RegisteredAddresses[i]; var lvl = i; var actOut = new ActiveOutput(addr, sig, lvl); activeOutputs.Add(actOut); } } return(resp.CurrentPhase, activeOutputs); }
public async Task <IActionResult> PostConfirmationAsync([FromQuery, Required] string uniqueId, [FromQuery, Required] long roundId) { if (roundId < 0 || !ModelState.IsValid) { return(BadRequest()); } using (await CoordinatorRound.ConnectionConfirmationLock.LockAsync()) { (CoordinatorRound round, Alice alice) = GetRunningRoundAndAliceOrFailureResponse(roundId, uniqueId, RoundPhase.ConnectionConfirmation, out IActionResult returnFailureResponse); if (returnFailureResponse != null) { return(returnFailureResponse); } RoundPhase phase = round.Phase; // Start building the response. var resp = new ConnectionConfirmationResponse { CurrentPhase = phase }; switch (phase) { case RoundPhase.InputRegistration: { round.StartAliceTimeout(alice.UniqueId); break; } case RoundPhase.ConnectionConfirmation: { resp.BlindedOutputSignatures = await round.ConfirmAliceConnectionAsync(alice); break; } default: { TryLogLateRequest(roundId, RoundPhase.ConnectionConfirmation); return(Gone($"Participation can be only confirmed from InputRegistration or ConnectionConfirmation phase. Current phase: {phase}.")); } } return(Ok(resp)); } }
public async Task <(RoundPhase currentPhase, IEnumerable <ActiveOutput> activeOutputs)> PostConfirmationAsync() { using HttpResponseMessage response = await TorClient.SendAsync(HttpMethod.Post, $"/api/v{WasabiClient.ApiVersion}/btc/chaumiancoinjoin/confirmation?uniqueId={UniqueId}&roundId={RoundId}").ConfigureAwait(false); if (response.StatusCode != HttpStatusCode.OK) { await response.ThrowRequestExceptionFromContentAsync().ConfigureAwait(false); } ConnectionConfirmationResponse resp = await response.Content.ReadAsJsonAsync <ConnectionConfirmationResponse>().ConfigureAwait(false); Logger.LogInfo($"Round ({RoundId}), Alice ({UniqueId}): Confirmed connection. Phase: {resp.CurrentPhase}."); var activeOutputs = new List <ActiveOutput>(); if (resp.BlindedOutputSignatures is { } && resp.BlindedOutputSignatures.Any())
public async Task <IActionResult> PostConfirmationAsync([FromQuery, Required] string uniqueId, [FromQuery, Required] long roundId) { if (roundId < 0 || !ModelState.IsValid) { return(BadRequest()); } (CoordinatorRound round, Alice alice) = GetRunningRoundAndAliceOrFailureResponse(roundId, uniqueId, RoundPhase.ConnectionConfirmation, out IActionResult returnFailureResponse); if (returnFailureResponse != null) { return(returnFailureResponse); } RoundPhase phase = round.Phase; // Start building the response. var resp = new ConnectionConfirmationResponse { CurrentPhase = phase }; switch (phase) { case RoundPhase.InputRegistration: { round.StartAliceTimeout(alice.UniqueId); break; } case RoundPhase.ConnectionConfirmation: { alice.State = AliceState.ConnectionConfirmed; int takeBlindCount = round.EstimateBestMixingLevel(alice); alice.BlindedOutputScripts = alice.BlindedOutputScripts[..takeBlindCount];