예제 #1
0
        public async Task <EmptyResponse> RegisterOutputCoreAsync(OutputRegistrationRequest request, CancellationToken cancellationToken)
        {
            using (await AsyncLock.LockAsync(cancellationToken).ConfigureAwait(false))
            {
                var round = GetRound(request.RoundId, Phase.OutputRegistration);

                var credentialAmount = -request.AmountCredentialRequests.Delta;

                Bob bob = new(request.Script, credentialAmount);

                var outputValue = bob.CalculateOutputAmount(round.FeeRate);

                var vsizeCredentialRequests = request.VsizeCredentialRequests;
                if (-vsizeCredentialRequests.Delta != bob.OutputVsize)
                {
                    throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.IncorrectRequestedVsizeCredentials, $"Round ({request.RoundId}): Incorrect requested vsize credentials.");
                }

                // Update the current round state with the additional output to ensure it's valid.
                var newState = round.AddOutput(new TxOut(outputValue, bob.Script));

                // Verify the credential requests and prepare their responses.
                await round.AmountCredentialIssuer.HandleRequestAsync(request.AmountCredentialRequests, cancellationToken).ConfigureAwait(false);

                await round.VsizeCredentialIssuer.HandleRequestAsync(vsizeCredentialRequests, cancellationToken).ConfigureAwait(false);

                // Update round state.
                round.Bobs.Add(bob);
                round.CoinjoinState = newState;
            }

            return(EmptyResponse.Instance);
        }
예제 #2
0
    public async Task <EmptyResponse> RegisterOutputCoreAsync(OutputRegistrationRequest request, CancellationToken cancellationToken)
    {
        using (await AsyncLock.LockAsync(cancellationToken).ConfigureAwait(false))
        {
            var round = GetRound(request.RoundId, Phase.OutputRegistration);

            var credentialAmount = -request.AmountCredentialRequests.Delta;

            if (CoinJoinScriptStore?.Contains(request.Script) is true)
            {
                Logger.LogWarning($"Round ({request.RoundId}): Already registered script.");
                throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.AlreadyRegisteredScript, $"Round ({request.RoundId}): Already registered script.");
            }

            var inputScripts = round.Alices.Select(a => a.Coin.ScriptPubKey).ToHashSet();
            if (inputScripts.Contains(request.Script))
            {
                Logger.LogWarning($"Round ({request.RoundId}): Already registered script in the round.");
                throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.AlreadyRegisteredScript, $"Round ({request.RoundId}): Already registered script in round.");
            }

            Bob bob = new(request.Script, credentialAmount);

            var outputValue = bob.CalculateOutputAmount(round.Parameters.MiningFeeRate);

            var vsizeCredentialRequests = request.VsizeCredentialRequests;
            if (-vsizeCredentialRequests.Delta != bob.OutputVsize)
            {
                throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.IncorrectRequestedVsizeCredentials, $"Round ({request.RoundId}): Incorrect requested vsize credentials.");
            }

            // Update the current round state with the additional output to ensure it's valid.
            var newState = round.AddOutput(new TxOut(outputValue, bob.Script));

            // Verify the credential requests and prepare their responses.
            await round.AmountCredentialIssuer.HandleRequestAsync(request.AmountCredentialRequests, cancellationToken).ConfigureAwait(false);

            await round.VsizeCredentialIssuer.HandleRequestAsync(vsizeCredentialRequests, cancellationToken).ConfigureAwait(false);

            // Update round state.
            round.Bobs.Add(bob);
            round.CoinjoinState = newState;
        }

        return(EmptyResponse.Instance);
    }
예제 #3
0
 public async Task RegisterOutputAsync(OutputRegistrationRequest request, CancellationToken cancellationToken)
 {
     await IdempotencyRequestCache.GetCachedResponseAsync(request, action : (request, token) => Arena.RegisterOutputCoreAsync(request, token), cancellationToken);
 }
예제 #4
0
 public Task <OutputRegistrationResponse> RegisterOutputAsync(OutputRegistrationRequest request, CancellationToken cancellableToken)
 {
     return(RequestHandler.RegisterOutputAsync(request, cancellableToken));
 }
예제 #5
0
 public Task RegisterOutputAsync(OutputRegistrationRequest request, CancellationToken cancellationToken) =>
 SendAndReceiveAsync <OutputRegistrationRequest>(RemoteAction.RegisterOutput, request, cancellationToken);
예제 #6
0
 public Task RegisterOutputAsync(OutputRegistrationRequest request, CancellationToken cancellationToken)
 {
     return(RegisterOutputCoreAsync(request, cancellationToken));
 }
 public Task <OutputRegistrationResponse> RegisterOutputAsync(OutputRegistrationRequest request, CancellationToken cancellationToken)
 => arena.RegisterOutputAsync(request);