예제 #1
0
 public CoinJoinManager(WalletManager walletManager, RoundStateUpdater roundStatusUpdater, IWasabiHttpClientFactory backendHttpClientFactory, ServiceConfiguration serviceConfiguration)
 {
     WalletManager        = walletManager;
     HttpClientFactory    = backendHttpClientFactory;
     RoundStatusUpdater   = roundStatusUpdater;
     ServiceConfiguration = serviceConfiguration;
 }
예제 #2
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);
    }
 public CoinJoinTrackerFactory(
     IWasabiHttpClientFactory httpClientFactory,
     RoundStateUpdater roundStatusUpdater,
     CancellationToken cancellationToken)
 {
     HttpClientFactory  = httpClientFactory;
     RoundStatusUpdater = roundStatusUpdater;
     CancellationToken  = cancellationToken;
 }
예제 #4
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);
예제 #5
0
 /// <param name="minAnonScoreTarget">Coins those have reached anonymity target, but still can be mixed if desired.</param>
 /// <param name="consolidationMode">If true, then aggressively try to consolidate as many coins as it can.</param>
 public CoinJoinClient(
     IWasabiHttpClientFactory httpClientFactory,
     IKeyChain keyChain,
     IDestinationProvider destinationProvider,
     RoundStateUpdater roundStatusUpdater,
     int minAnonScoreTarget = int.MaxValue,
     bool consolidationMode = false,
     TimeSpan doNotRegisterInLastMinuteTimeLimit = default)
 {
     HttpClientFactory   = httpClientFactory;
     KeyChain            = keyChain;
     DestinationProvider = destinationProvider;
     RoundStatusUpdater  = roundStatusUpdater;
     MinAnonScoreTarget  = minAnonScoreTarget;
     ConsolidationMode   = consolidationMode;
     SecureRandom        = new SecureRandom();
     DoNotRegisterInLastMinuteTimeLimit = doNotRegisterInLastMinuteTimeLimit;
 }
예제 #6
0
    public static async Task <AliceClient> CreateRegisterAndConfirmInputAsync(
        RoundState roundState,
        ArenaClient arenaClient,
        SmartCoin coin,
        IKeyChain keyChain,
        RoundStateUpdater roundStatusUpdater,
        CancellationToken cancellationToken)
    {
        AliceClient?aliceClient = null;

        try
        {
            aliceClient = await RegisterInputAsync(roundState, arenaClient, coin, keyChain, cancellationToken).ConfigureAwait(false);

            await aliceClient.ConfirmConnectionAsync(roundStatusUpdater, cancellationToken).ConfigureAwait(false);

            Logger.LogInfo($"Round ({aliceClient.RoundId}), Alice ({aliceClient.AliceId}): Connection was confirmed.");
        }
        catch (OperationCanceledException)
        {
            if (aliceClient is { })
        public async Task SoloCoinJoinTest()
        {
            const int InputCount = 2;

            // At the end of the test a coinjoin transaction has to be created and broadcasted.
            var transactionCompleted = new TaskCompletionSource <Transaction>();

            // Total test timeout.
            using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(120));
            cts.Token.Register(() => transactionCompleted.TrySetCanceled(), useSynchronizationContext: false);

            // Create a key manager and use it to create two fake coins.
            var keyManager = KeyManager.CreateNew(out var _, password: "");

            keyManager.AssertCleanKeysIndexed();
            var coins = keyManager.GetKeys()
                        .Take(InputCount)
                        .Select(x => new Coin(
                                    BitcoinFactory.CreateOutPoint(),
                                    new TxOut(Money.Coins(1), x.P2wpkhScript)))
                        .ToArray();

            var httpClient = _apiApplicationFactory.WithWebHostBuilder(builder =>
            {
                builder.ConfigureServices(services =>
                {
                    var rpc = BitcoinFactory.GetMockMinimalRpc();

                    // Make the coordinator to believe that those two coins are real and
                    // that they exist in the blockchain with many confirmations.
                    rpc.OnGetTxOutAsync = (txId, idx, _) => new()
                    {
                        Confirmations    = 101,
                        IsCoinBase       = false,
                        ScriptPubKeyType = "witness_v0_keyhash",
                        TxOut            = coins.Single(x => x.Outpoint.Hash == txId && x.Outpoint.N == idx).TxOut
                    };

                    // Make the coordinator believe that the transaction is being
                    // broadcasted using the RPC interface. Once we receive this tx
                    // (the `SendRawTransationAsync` was invoked) we stop waiting
                    // and finish the waiting tasks to finish the test successfully.
                    rpc.OnSendRawTransactionAsync = (tx) =>
                    {
                        transactionCompleted.SetResult(tx);
                        return(tx.GetHash());
                    };

                    // Instruct the coodinator DI container to use these two scoped
                    // services to build everything (wabisabi controller, arena, etc)
                    services.AddScoped <IRPCClient>(s => rpc);
                    services.AddScoped <WabiSabiConfig>(s => new WabiSabiConfig {
                        MaxInputCountByRound = InputCount
                    });
                });
            }).CreateClient();

            // Create the coinjoin client
            var apiClient = _apiApplicationFactory.CreateWabiSabiHttpApiClient(httpClient);

            using var roundStateUpdater = new RoundStateUpdater(TimeSpan.FromSeconds(1), apiClient);
            await roundStateUpdater.StartAsync(CancellationToken.None);

            var kitchen = new Kitchen();

            kitchen.Cook("");

            var coinJoinClient = new CoinJoinClient(apiClient, coins, kitchen, keyManager, roundStateUpdater);

            // Run the coinjoin client task.
            await coinJoinClient.StartCoinJoinAsync(cts.Token);

            var boadcastedTx = await transactionCompleted.Task.ConfigureAwait(false);             // wait for the transaction to be broadcasted.

            Assert.NotNull(boadcastedTx);

            await roundStateUpdater.StopAsync(CancellationToken.None);
        }