public async Task ConfigureAsync(TumblerClientConfiguration configuration, ClientInteraction interaction)
        {
            interaction = interaction ?? new AcceptAllClientInteraction();

            Network       = configuration.Network;
            TumblerServer = configuration.TumblerServer;
            BobSettings   = configuration.BobConnectionSettings;
            AliceSettings = configuration.AliceConnectionSettings;
            AllowInsecure = configuration.AllowInsecure;

            await SetupTorAsync(interaction, configuration.TorPath).ConfigureAwait(false);

            RPCClient rpc = null;

            try
            {
                rpc = configuration.RPCArgs.ConfigureRPCClient(configuration.Network);
            }
            catch
            {
                throw new ConfigException("Please, fix rpc settings in " + configuration.ConfigurationFile);
            }

            var dbreeze = new DBreezeRepository(Path.Combine(configuration.DataDir, "db2"));

            Cooperative = configuration.Cooperative;
            Repository  = dbreeze;
            _Disposables.Add(dbreeze);
            Tracker  = new Tracker(dbreeze, Network);
            Services = ExternalServices.CreateFromRPCClient(rpc, dbreeze, Tracker);

            if (configuration.OutputWallet.RootKey != null && configuration.OutputWallet.KeyPath != null)
            {
                DestinationWallet = new ClientDestinationWallet(configuration.OutputWallet.RootKey, configuration.OutputWallet.KeyPath, dbreeze, configuration.Network);
            }
            else if (configuration.OutputWallet.RPCArgs != null)
            {
                try
                {
                    DestinationWallet = new RPCDestinationWallet(configuration.OutputWallet.RPCArgs.ConfigureRPCClient(Network));
                }
                catch
                {
                    throw new ConfigException("Please, fix outputwallet rpc settings in " + configuration.ConfigurationFile);
                }
            }
            else
            {
                throw new ConfigException("Missing configuration for outputwallet");
            }

            TumblerParameters = dbreeze.Get <ClassicTumbler.ClassicTumblerParameters>("Configuration", configuration.TumblerServer.Uri.AbsoluteUri);

            if (TumblerParameters != null && TumblerParameters.GetHash() != configuration.TumblerServer.ConfigurationHash)
            {
                TumblerParameters = null;
            }

            if (!configuration.OnlyMonitor)
            {
                var client = CreateTumblerClient(0);
                if (TumblerParameters == null)
                {
                    Logs.Configuration.LogInformation("Downloading tumbler information of " + configuration.TumblerServer.Uri.AbsoluteUri);
                    var parameters = Retry(3, () => client.GetTumblerParameters());
                    if (parameters == null)
                    {
                        throw new ConfigException("Unable to download tumbler's parameters");
                    }

                    if (parameters.GetHash() != configuration.TumblerServer.ConfigurationHash)
                    {
                        throw new ConfigException("The tumbler returned an invalid configuration");
                    }

                    var standardCycles = new StandardCycles(configuration.Network);
                    var standardCycle  = standardCycles.GetStandardCycle(parameters);

                    if (standardCycle == null || !parameters.IsStandard())
                    {
                        Logs.Configuration.LogWarning("This tumbler has non standard parameters");
                        if (!AllowInsecure)
                        {
                            throw new ConfigException("This tumbler has non standard parameters");
                        }
                        standardCycle = null;
                    }

                    await interaction.ConfirmParametersAsync(parameters, standardCycle).ConfigureAwait(false);

                    Repository.UpdateOrInsert("Configuration", TumblerServer.Uri.AbsoluteUri, parameters, (o, n) => n);
                    TumblerParameters = parameters;

                    Logs.Configuration.LogInformation("Tumbler parameters saved");
                }

                Logs.Configuration.LogInformation($"Using tumbler {TumblerServer.Uri.AbsoluteUri}");
            }
        }
Пример #2
0
        private static void StartTumbler(string[] args)
        {
            Logs.Configure(new FuncLoggerFactory(i => new ConsoleLogger(i, (a, b) => true, false)));
            CancellationTokenSource broadcasterCancel = new CancellationTokenSource();
            DBreezeRepository       dbreeze           = null;

            try
            {
                var network = args.Contains("-testnet", StringComparer.OrdinalIgnoreCase) ? Network.TestNet :
                              args.Contains("-regtest", StringComparer.OrdinalIgnoreCase) ? Network.RegTest :
                              Network.Main;
                Logs.Configuration.LogInformation("Network: " + network);

                var dataDir     = DefaultDataDirectory.GetDefaultDirectory("NTumbleBit", network);
                var consoleArgs = new TextFileConfiguration(args);
                var configFile  = GetDefaultConfigurationFile(dataDir, network);
                var config      = TextFileConfiguration.Parse(File.ReadAllText(configFile));
                consoleArgs.MergeInto(config, true);
                config.AddAlias("server", "tumbler.server");

                var onlymonitor = config.GetOrDefault <bool>("onlymonitor", false);

                RPCClient rpc = null;
                try
                {
                    rpc = RPCArgs.ConfigureRPCClient(config, network);
                }
                catch
                {
                    throw new ConfigException("Please, fix rpc settings in " + configFile);
                }
                dbreeze = new DBreezeRepository(Path.Combine(dataDir, "db"));

                var services = ExternalServices.CreateFromRPCClient(rpc, dbreeze);

                var broadcaster = new BroadcasterJob(services, Logs.Main);
                broadcaster.Start(broadcasterCancel.Token);
                Logs.Main.LogInformation("BroadcasterJob started");

                if (!onlymonitor)
                {
                    var server = config.GetOrDefault("tumbler.server", null as Uri);
                    if (server == null)
                    {
                        Logs.Main.LogError("tumbler.server not configured");
                        throw new ConfigException();
                    }
                    var client = new TumblerClient(network, server);
                    Logs.Configuration.LogInformation("Downloading tumbler information of " + server.AbsoluteUri);
                    var parameters = Retry(3, () => client.GetTumblerParameters());
                    Logs.Configuration.LogInformation("Tumbler Server Connection successfull");
                    var existingConfig = dbreeze.Get <ClassicTumbler.ClassicTumblerParameters>("Configuration", client.Address.AbsoluteUri);
                    if (existingConfig != null)
                    {
                        if (Serializer.ToString(existingConfig) != Serializer.ToString(parameters))
                        {
                            Logs.Configuration.LogError("The configuration file of the tumbler changed since last connection, it should never happen");
                            throw new ConfigException();
                        }
                    }
                    else
                    {
                        dbreeze.UpdateOrInsert("Configuration", client.Address.AbsoluteUri, parameters, (o, n) => n);
                    }

                    if (parameters.Network != rpc.Network)
                    {
                        throw new ConfigException("The tumbler server run on a different network than the local rpc server");
                    }

                    IDestinationWallet destinationWallet = null;
                    try
                    {
                        destinationWallet = GetDestinationWallet(config, rpc.Network, dbreeze);
                    }
                    catch (Exception ex)
                    {
                        Logs.Main.LogInformation("outputwallet.extpubkey is not configured, trying to use outputwallet.rpc settings.");
                        try
                        {
                            destinationWallet = GetRPCDestinationWallet(config, rpc.Network);
                        }
                        catch { throw ex; }                         //Not a bug, want to throw the other exception
                    }
                    var stateMachine = new StateMachinesExecutor(parameters, client, destinationWallet, services, dbreeze, Logs.Main);
                    stateMachine.Start(broadcasterCancel.Token);
                    Logs.Main.LogInformation("State machines started");
                }
                Logs.Main.LogInformation("Press enter to stop");
                Console.ReadLine();
                broadcasterCancel.Cancel();
            }
            catch (ConfigException ex)
            {
                if (!string.IsNullOrEmpty(ex.Message))
                {
                    Logs.Configuration.LogError(ex.Message);
                }
            }
            catch (Exception ex)
            {
                Logs.Configuration.LogError(ex.Message);
                Logs.Configuration.LogDebug(ex.StackTrace);
            }
            finally
            {
                if (!broadcasterCancel.IsCancellationRequested)
                {
                    broadcasterCancel.Cancel();
                }
                dbreeze?.Dispose();
            }
        }