Esempio n. 1
0
    public async Task StartParticipatingAsync(CancellationToken cancellationToken)
    {
        ThrowIfDisposed();
        var apiClient = new WabiSabiHttpApiClient(HttpClientFactory.NewHttpClientWithDefaultCircuit());

        using var roundStateUpdater = new RoundStateUpdater(TimeSpan.FromSeconds(3), apiClient);
        await roundStateUpdater.StartAsync(cancellationToken).ConfigureAwait(false);

        var coinJoinClient = new CoinJoinClient(
            HttpClientFactory,
            Wallet,
            Wallet,
            roundStateUpdater,
            consolidationMode: true);

        // Run the coinjoin client task.
        var walletHdPubKey = new HdPubKey(Wallet.PubKey, KeyPath.Parse("m/84'/0/0/0/0"), SmartLabel.Empty, KeyState.Clean);

        walletHdPubKey.SetAnonymitySet(1);         // bug if not settled

        if (SplitTransaction is null)
        {
            throw new InvalidOperationException($"{nameof(GenerateCoinsAsync)} has to be called first.");
        }

        var smartCoins = SplitTransaction.Transaction.Outputs.AsIndexedOutputs()
                         .Select(x => new SmartCoin(SplitTransaction, x.N, walletHdPubKey))
                         .ToList();

        // Run the coinjoin client task.
        await coinJoinClient.StartCoinJoinAsync(smartCoins, cancellationToken).ConfigureAwait(false);

        await roundStateUpdater.StopAsync(cancellationToken).ConfigureAwait(false);
    }
Esempio n. 2
0
        public Participant(IRPCClient rpc, WabiSabiHttpApiClient apiClient)
        {
            Rpc       = rpc;
            ApiClient = apiClient;

            KeyManager = KeyManager.CreateNew(out var _, password: "");
            KeyManager.AssertCleanKeysIndexed();
        }
Esempio n. 3
0
    private BobClient CreateBobClient(RoundState roundState)
    {
        var arenaRequestHandler = new WabiSabiHttpApiClient(HttpClientFactory.NewHttpClientWithCircuitPerRequest());

        return(new BobClient(
                   roundState.Id,
                   new(
                       roundState.CreateAmountCredentialClient(SecureRandom),
                       roundState.CreateVsizeCredentialClient(SecureRandom),
                       arenaRequestHandler)));
    }
Esempio n. 4
0
    public async Task <ArenaClient> CreateArenaClientAsync(WabiSabiHttpApiClient wabiSabiHttpApiClient)
    {
        var rounds         = (await wabiSabiHttpApiClient.GetStatusAsync(RoundStateRequest.Empty, CancellationToken.None)).RoundStates;
        var round          = rounds.First(x => x.CoinjoinState is ConstructionState);
        var insecureRandom = new InsecureRandom();
        var arenaClient    = new ArenaClient(
            round.CreateAmountCredentialClient(insecureRandom),
            round.CreateVsizeCredentialClient(insecureRandom),
            wabiSabiHttpApiClient);

        return(arenaClient);
    }
Esempio n. 5
0
    public async Task StartParticipatingAsync(CancellationToken cancellationToken)
    {
        if (SplitTransaction is null)
        {
            throw new InvalidOperationException($"{nameof(GenerateCoinsAsync)} has to be called first.");
        }

        var apiClient = new WabiSabiHttpApiClient(HttpClientFactory.NewHttpClientWithDefaultCircuit());

        using var roundStateUpdater = new RoundStateUpdater(TimeSpan.FromSeconds(3), apiClient);
        await roundStateUpdater.StartAsync(cancellationToken).ConfigureAwait(false);

        var coinJoinClient = WabiSabiFactory.CreateTestCoinJoinClient(HttpClientFactory, Wallet, Wallet, roundStateUpdater);
Esempio n. 6
0
    private async Task <ImmutableArray <(AliceClient AliceClient, PersonCircuit PersonCircuit)> > CreateRegisterAndConfirmCoinsAsync(IEnumerable <SmartCoin> smartCoins, RoundState roundState, CancellationToken cancellationToken)
    {
        int eventInvokedAlready = 0;

        async Task <(AliceClient?AliceClient, PersonCircuit?PersonCircuit)> RegisterInputAsync(SmartCoin coin, CancellationToken cancellationToken)
        {
            PersonCircuit?personCircuit = null;

            try
            {
                personCircuit = HttpClientFactory.NewHttpClientWithPersonCircuit(out Tor.Http.IHttpClient httpClient);

                // Alice client requests are inherently linkable to each other, so the circuit can be reused
                var arenaRequestHandler = new WabiSabiHttpApiClient(httpClient);

                var aliceArenaClient = new ArenaClient(
                    roundState.CreateAmountCredentialClient(SecureRandom),
                    roundState.CreateVsizeCredentialClient(SecureRandom),
                    arenaRequestHandler);

                var aliceClient = await AliceClient.CreateRegisterAndConfirmInputAsync(roundState, aliceArenaClient, coin, KeyChain, RoundStatusUpdater, cancellationToken).ConfigureAwait(false);

                // Right after the first real-cred confirmation happened we entered into critical phase.
                if (Interlocked.Exchange(ref eventInvokedAlready, 1) == 0)
                {
                    CoinJoinClientProgress.SafeInvoke(this, new EnteringCriticalPhase());
                }

                return(aliceClient, personCircuit);
            }
            catch (WabiSabiProtocolException)
            {
                personCircuit?.Dispose();
                return(null, null);
            }
            catch (Exception)
            {
                personCircuit?.Dispose();
                throw;
            }
        }

        // Gets the list of scheduled dates/time in the remaining available time frame when each alice has to be registered.
        var remainingTimeForRegistration = roundState.InputRegistrationEnd - DateTimeOffset.UtcNow;

        roundState.LogDebug($"Inputs({smartCoins.Count()}) registration started - it will end in: {remainingTimeForRegistration:hh\\:mm\\:ss}.");

        var scheduledDates = GetScheduledDates(smartCoins.Count(), roundState.InputRegistrationEnd);

        // Creates scheduled tasks (tasks that wait until the specified date/time and then perform the real registration)
        var aliceClients = smartCoins.Zip(
            scheduledDates,
            async(coin, date) =>
        {
            var delay = date - DateTimeOffset.UtcNow;
            if (delay > TimeSpan.Zero)
            {
                await Task.Delay(delay, cancellationToken).ConfigureAwait(false);
            }
            return(await RegisterInputAsync(coin, cancellationToken).ConfigureAwait(false));
        })
                           .ToImmutableArray();

        await Task.WhenAll(aliceClients).ConfigureAwait(false);

        return(aliceClients
               .Select(x => x.Result)
               .Where(r => r.AliceClient is not null && r.PersonCircuit is not null)
               .Select(r => (r.AliceClient !, r.PersonCircuit !))
               .ToImmutableArray());
    }