예제 #1
0
        public void Run(string[] args)
        {
            NetworksSelector networkSet = x42.Networks.Networks.x42;
            var argsConf = new TextFileConfiguration(args);
            var debug    = argsConf.GetOrDefault <bool>("debug", false);

            ConsoleLoggerProcessor loggerProcessor = new ConsoleLoggerProcessor();

            Logs.Configure(new FuncLoggerFactory(i => new CustomerConsoleLogger(i, Logs.SupportDebug(debug), null, loggerProcessor)));

            using (var interactive = new Interactive())
            {
                var config = new TumblerConfiguration();
                config.LoadArgs(networkSet, args);
                try
                {
                    var runtime = TumblerRuntime.FromConfiguration(config, new TextWriterClientInteraction(Console.Out, Console.In));
                    interactive.Runtime = new ServerInteractiveRuntime(runtime);
                    StoppableWebHost host = null;
                    if (!config.OnlyMonitor)
                    {
                        host = new StoppableWebHost(() => new WebHostBuilder()
                                                    .UseAppConfiguration(runtime)
                                                    .UseContentRoot(Directory.GetCurrentDirectory())
                                                    .UseStartup <Startup>()
                                                    .Build());
                    }

                    var job = new BroadcasterJob(interactive.Runtime.Services);
                    job.Start();
                    interactive.Services.Add(job);

                    var tor = new TorRegisterJob(config, runtime);
                    tor.Start();
                    interactive.Services.Add(tor);

                    if (!config.OnlyMonitor)
                    {
                        host.Start();
                        interactive.Services.Add(host);
                    }

                    interactive.StartInteractive();
                }
                catch (ConfigException ex)
                {
                    if (!string.IsNullOrEmpty(ex.Message))
                    {
                        Logs.Configuration.LogError(ex.Message);
                    }
                }
                catch (InterruptedConsoleException) { }
                catch (Exception exception)
                {
                    Logs.Tumbler.LogError("Exception thrown while running the server");
                    Logs.Tumbler.LogError(exception.ToString());
                }
            }
        }
예제 #2
0
 public UiNodeSettings(
     Network network = null,
     ProtocolVersion protocolVersion = SupportedProtocolVersion,
     string agent  = "StratisNode",
     string[] args = null,
     NetworksSelector networksSelector = null)
     : base(
         network, protocolVersion, agent, args, networksSelector)
 {
 }
예제 #3
0
        /// <summary>
        /// Initializes a new instance of the object.
        /// </summary>
        /// <param name="network">The network the node runs on - regtest/testnet/mainnet.</param>
        /// <param name="protocolVersion">Supported protocol version for which to create the configuration.</param>
        /// <param name="agent">The nodes user agent that will be shared with peers.</param>
        /// <param name="args">The command-line arguments.</param>
        /// <param name="networksSelector">A selector class that delayed load a network for either - regtest/testnet/mainnet.</param>
        /// <exception cref="ConfigurationException">Thrown in case of any problems with the configuration file or command line arguments.</exception>
        /// <remarks>
        /// Processing depends on whether a configuration file is passed via the command line.
        /// There are two main scenarios here:
        /// - The configuration file is passed via the command line. In this case we need
        ///   to read it earlier so that it can provide defaults for "testnet" and "regtest".
        /// - Alternatively, if the file name is not supplied then a network-specific file
        ///   name would be determined. In this case we first need to determine the network.
        /// </remarks>
        public NodeSettings(Network network = null, ProtocolVersion protocolVersion = SupportedProtocolVersion,
                            string agent    = "ImpleumNode", string[] args          = null, NetworksSelector networksSelector = null)
        {
            // Create the default logger factory and logger.
            var loggerFactory = new ExtendedLoggerFactory();

            this.LoggerFactory = loggerFactory;
            this.LoggerFactory.AddConsoleWithFilters();
            this.LoggerFactory.AddNLog();
            this.Logger = this.LoggerFactory.CreateLogger(typeof(NodeSettings).FullName);

            // Record arguments.
            this.Network         = network;
            this.ProtocolVersion = protocolVersion;
            this.Agent           = agent;
            this.ConfigReader    = new TextFileConfiguration(args ?? new string[] { });

            // Log arguments.
            this.Logger.LogDebug("Arguments: network='{0}', protocolVersion='{1}', agent='{2}', args='{3}'.",
                                 this.Network == null ? "(None)" : this.Network.Name,
                                 this.ProtocolVersion,
                                 this.Agent,
                                 args == null ? "(None)" : string.Join(" ", args));

            // By default, we look for a file named '<network>.conf' in the network's data directory,
            // but both the data directory and the configuration file path may be changed using the -datadir and -conf command-line arguments.
            this.ConfigurationFile = this.ConfigReader.GetOrDefault <string>("conf", null, this.Logger)?.NormalizeDirectorySeparator();
            this.DataDir           = this.ConfigReader.GetOrDefault <string>("datadir", null, this.Logger)?.NormalizeDirectorySeparator();
            this.DataDirRoot       = this.ConfigReader.GetOrDefault <string>("datadirroot", "ImpleumNode", this.Logger);

            // If the configuration file is relative then assume it is relative to the data folder and combine the paths.
            if (this.DataDir != null && this.ConfigurationFile != null)
            {
                bool isRelativePath = Path.GetFullPath(this.ConfigurationFile).Length > this.ConfigurationFile.Length;
                if (isRelativePath)
                {
                    this.ConfigurationFile = Path.Combine(this.DataDir, this.ConfigurationFile);
                }
            }

            // If the configuration file has been specified on the command line then read it now
            // so that it can provide the defaults for testnet and regtest.
            if (this.ConfigurationFile != null)
            {
                // If the configuration file was specified on the command line then it must exist.
                if (!File.Exists(this.ConfigurationFile))
                {
                    throw new ConfigurationException($"Configuration file does not exist at {this.ConfigurationFile}.");
                }

                // Sets the ConfigReader based on the arguments and the configuration file if it exists.
                this.ReadConfigurationFile();
            }

            // If the network is not known then derive it from the command line arguments.
            if (this.Network == null)
            {
                if (networksSelector == null)
                {
                    throw new ConfigurationException("Network or NetworkSelector not provided.");
                }

                // Find out if we need to run on testnet or regtest from the config file.
                bool testNet = this.ConfigReader.GetOrDefault <bool>("testnet", false, this.Logger);
                bool regTest = this.ConfigReader.GetOrDefault <bool>("regtest", false, this.Logger);

                if (testNet && regTest)
                {
                    throw new ConfigurationException("Invalid combination of regtest and testnet.");
                }

                this.Network = testNet ? networksSelector.Testnet() : regTest?networksSelector.Regtest() : networksSelector.Mainnet();

                this.Logger.LogDebug("Network set to '{0}'.", this.Network.Name);
            }

            // Ensure the network being used is registered and we have the correct Network object reference.
            this.Network = NetworkRegistration.Register(this.Network);

            // Set the full data directory path.
            if (this.DataDir == null)
            {
                // Create the data directories if they don't exist.
                this.DataDir = this.CreateDefaultDataDirectories(Path.Combine(this.DataDirRoot, this.Network.RootFolderName), this.Network);
            }
            else
            {
                // Combine the data directory with the network's root folder and name.
                string directoryPath = Path.Combine(this.DataDir, this.Network.RootFolderName, this.Network.Name);
                this.DataDir = Directory.CreateDirectory(directoryPath).FullName;
                this.Logger.LogDebug("Data directory initialized with path {0}.", this.DataDir);
            }

            // Set the data folder.
            this.DataFolder = new DataFolder(this.DataDir);

            // Attempt to load NLog configuration from the DataFolder.
            loggerFactory.LoadNLogConfiguration(this.DataFolder);

            // Get the configuration file name for the network if it was not specified on the command line.
            if (this.ConfigurationFile == null)
            {
                this.ConfigurationFile = Path.Combine(this.DataDir, this.Network.DefaultConfigFilename);
                this.Logger.LogDebug("Configuration file set to '{0}'.", this.ConfigurationFile);

                if (File.Exists(this.ConfigurationFile))
                {
                    this.ReadConfigurationFile();
                }
            }

            // Create the custom logger factory.
            this.Log = new LogSettings();
            this.Log.Load(this.ConfigReader);
            this.LoggerFactory.AddFilters(this.Log, this.DataFolder);
            this.LoggerFactory.ConfigureConsoleFilters(this.LoggerFactory.GetConsoleSettings(), this.Log);

            // Load the configuration.
            this.LoadConfiguration();
        }
예제 #4
0
        /// <summary>
        /// The expected sequence of arguments:
        /// <list>
        /// <item>
        /// 1, [network-name] [options] [rpc-command] [rpc-params].
        /// </item>
        /// <item>
        /// 2, [network-name] [options] [api-controller "/" api-command] [api-params].
        /// </item>
        /// </list>
        /// </summary>
        public static void Main(string[] args)
        {
            try
            {
                // Preprocess the command line arguments
                var argList = new List <string>(args);

                string networkName = null;
                if (argList.Any())
                {
                    networkName = argList.First();
                    argList.RemoveAt(0);
                }

                var optionList = new List <string>();
                while ((argList.Any()) && (argList[0].StartsWith('-')))
                {
                    optionList.Add(argList[0]);
                    argList.RemoveAt(0);
                }

                string method = "";
                if (argList.Any())
                {
                    method = argList.First().ToUpper();
                    if (method == "GET" || method == "POST" || method == "DELETE")
                    {
                        argList.RemoveAt(0);
                    }
                    else
                    {
                        method = "";
                    }
                }

                string command = string.Empty;
                if (argList.Any())
                {
                    command = argList.First();
                    argList.RemoveAt(0);
                }

                var commandArgList = new List <string>(argList);

                // Display help if required.
                if (optionList.Contains("-help") || optionList.Contains("--help") || string.IsNullOrWhiteSpace(command))
                {
                    var builder = new StringBuilder();
                    builder.AppendLine("Usage:");
                    builder.AppendLine(" dotnet run <Stratis.Bitcoin.Cli/Stratis.Bitcoin.Cli.dll> [network-name] [options] [method] <command> [arguments]");
                    builder.AppendLine();
                    builder.AppendLine("Command line arguments:");
                    builder.AppendLine();
                    builder.AppendLine("[network-name]                     Name of the network - e.g. \"strax\" or \"bitcoin\".");
                    builder.AppendLine("[options]                          Options for the CLI (optional) - e.g. -help, -rpcuser, see below.");
                    builder.AppendLine("[method]                           Method to use for API calls - 'GET', 'POST' or 'DELETE'.");
                    builder.AppendLine("[command]                          Name of RPC method or API <controller>/<method>.");
                    builder.AppendLine("[arguments]                        Argument by position (RPC) or Name = Value pairs (API) (optional).");
                    builder.AppendLine();
                    builder.AppendLine("Options:");
                    builder.AppendLine("-help                              This help message");
                    builder.AppendLine("-rpcconnect=<ip>                   Send commands to node running on <ip> (default: 127.0.0.1)");
                    builder.AppendLine("-rpcport=<port>                    Connect to JSON-RPC on <port> (default for Strax: 18000 (mainnet), 18100 (testnet) or default for Bitcoin: 8332)");
                    builder.AppendLine("-rpcuser=<user>                    Username for JSON-RPC connections");
                    builder.AppendLine("-rpcpassword=<pw>                  Password for JSON-RPC connections");
                    builder.AppendLine();
                    builder.AppendLine("Examples:");
                    builder.AppendLine();
                    builder.AppendLine("dotnet run stratis -testnet GET Wallet/history WalletName=testwallet - Lists all the historical transactions of the wallet called 'testwallet' on the stratis test network.");
                    builder.AppendLine("dotnet run stratis -rpcuser=stratistestuser -rpcpassword=stratistestpassword -rpcconnect=127.0.0.3 -rpcport=26174 getinfo - Displays general information about the Stratis node on the 127.0.0.3:26174, authenticating with the RPC specified user.");
                    builder.AppendLine("dotnet run bitcoin -rpcuser=btctestuser -rpcpassword=btctestpass getbalance - Displays the current balance of the opened wallet on the 127.0.0.1:8332 node, authenticating with the RPC specified user.");
                    Console.WriteLine(builder);
                    return;
                }

                // Determine API port.
                NetworksSelector networksSelector = null;

                if (networkName.Contains("strax"))
                {
                    networksSelector = Networks.Networks.Strax;
                }
                else if (networkName.Contains("stratis"))
                {
                    networksSelector = Networks.Networks.Stratis;
                }
                else
                {
                    networksSelector = Networks.Networks.Bitcoin;
                }

                // API calls require both the controller name and the method name separated by "/".
                // If this is not an API call then assume it is an RPC call.
                if (!command.Contains("/"))
                {
                    // Process RPC call.
                    try
                    {
                        string[] options      = optionList.Append("-server").ToArray();
                        var      nodeSettings = new NodeSettings(networksSelector: networksSelector, protocolVersion: ProtocolVersion.PROVEN_HEADER_VERSION, args: options)
                        {
                            MinProtocolVersion = ProtocolVersion.ALT_PROTOCOL_VERSION
                        };

                        var     rpcSettings = new RpcSettings(nodeSettings);
                        Network network     = nodeSettings.Network;

                        // Find the binding to 127.0.0.1 or the first available. The logic in RPC settings ensures there will be at least 1.
                        System.Net.IPEndPoint nodeEndPoint = rpcSettings.Bind.FirstOrDefault(b => b.Address.ToString() == "127.0.0.1") ?? rpcSettings.Bind[0];
                        var rpcUri = new Uri($"http://{nodeEndPoint}");

                        // Process the command line RPC arguments
                        // TODO: this should probably be moved to the NodeSettings.FromArguments
                        if (options.GetValueOf("-rpcbind") != null)
                        {
                            rpcUri = new Uri($"http://{options.GetValueOf("-rpcbind")}");
                        }

                        if (options.GetValueOf("-rpcconnect") != null || options.GetValueOf("-rpcport") != null)
                        {
                            string rpcAddress = options.GetValueOf("-rpcconnect") ?? "127.0.0.1";

                            int rpcPort = rpcSettings.RPCPort;
                            int.TryParse(options.GetValueOf("-rpcport"), out rpcPort);

                            rpcUri = new Uri($"http://{rpcAddress}:{rpcPort}");
                        }
                        rpcSettings.RpcUser     = options.GetValueOf("-rpcuser") ?? rpcSettings.RpcUser;
                        rpcSettings.RpcPassword = options.GetValueOf("-rpcpassword") ?? rpcSettings.RpcPassword;

                        Console.WriteLine($"Connecting to the following RPC node: http://{rpcSettings.RpcUser}:{rpcSettings.RpcPassword}@{rpcUri.Authority}.");

                        // Initialize the RPC client with the configured or passed userid, password and endpoint.
                        var rpcClient = new RPCClient($"{rpcSettings.RpcUser}:{rpcSettings.RpcPassword}", rpcUri, network);

                        // Execute the RPC command
                        Console.WriteLine($"Sending RPC command '{command} {string.Join(" ", commandArgList)}' to '{rpcUri}'.");
                        RPCResponse response = rpcClient.SendCommand(command, commandArgList.ToArray());

                        // Return the result as a string to the console.
                        Console.WriteLine(response.ResultString);
                    }
                    catch (Exception err)
                    {
                        Console.WriteLine(err.Message);
                    }
                }
                else
                {
                    // Process API call.
                    string[] options      = optionList.ToArray();
                    var      nodeSettings = new NodeSettings(networksSelector: networksSelector, protocolVersion: ProtocolVersion.PROVEN_HEADER_VERSION, args: options)
                    {
                        MinProtocolVersion = ProtocolVersion.ALT_PROTOCOL_VERSION
                    };

                    var apiSettings = new ApiSettings(nodeSettings);

                    string url = $"http://localhost:{apiSettings.ApiPort}/api".AppendPathSegment(command);

                    object commandArgObj = GetAnonymousObjectFromDictionary(commandArgList
                                                                            .Select(a => a.Split('='))
                                                                            .ToDictionary(a => a[0], a => a[1]));

                    HttpResponseMessage httpResponse;

                    switch (method)
                    {
                    case "POST":
                        httpResponse = CallApiPost(url, commandArgObj);
                        break;

                    case "DELETE":
                        httpResponse = CallApiDelete(url, commandArgObj);
                        break;

                    default:
                        httpResponse = CallApiGet(url, commandArgObj);
                        break;
                    }

                    var response = httpResponse.Content.ReadAsStringAsync().GetAwaiter().GetResult();

                    // Format and return the result as a string to the console.
                    Console.WriteLine(JsonConvert.SerializeObject(JsonConvert.DeserializeObject <object>(response), Formatting.Indented));
                }
            }
            catch (Exception err)
            {
                // Report any errors to the console.
                Console.WriteLine(ExceptionToString(err));
            }
        }
예제 #5
0
        public void Run(string[] args)
        {
            NetworksSelector networkSet = x42.Networks.Networks.x42;
            var argsConf      = new TextFileConfiguration(args);
            var debug         = argsConf.GetOrDefault <bool>("debug", false);
            var redeemEscrows = argsConf.GetOrDefault <bool>("redeemescrows", false);;

            ConsoleLoggerProcessor loggerProcessor = new ConsoleLoggerProcessor();

            Logs.Configure(new FuncLoggerFactory(i => new CustomerConsoleLogger(i, Logs.SupportDebug(debug), null, loggerProcessor)));
            using (var interactive = new Interactive())
            {
                try
                {
                    var config = new TumblerClientConfiguration();
                    config.LoadArgs(networkSet, args);

                    var runtime = TumblerClientRuntime.FromConfiguration(config, new TextWriterClientInteraction(Console.Out, Console.In));
                    interactive.Runtime = new ClientInteractiveRuntime(runtime);

                    if (redeemEscrows)
                    {
                        RedeemEscrows(runtime).GetAwaiter().GetResult();
                    }


                    var broadcaster = runtime.CreateBroadcasterJob();
                    broadcaster.Start();
                    interactive.Services.Add(broadcaster);
                    //interactive.Services.Add(new CheckIpService(runtime));
                    //interactive.Services.Last().Start();

                    if (!config.OnlyMonitor)
                    {
                        var stateMachine = runtime.CreateStateMachineJob();
                        stateMachine.Start();
                        interactive.Services.Add(stateMachine);
                    }

                    interactive.StartInteractive();
                }
                catch (ClientInteractionException ex)
                {
                    if (!string.IsNullOrEmpty(ex.Message))
                    {
                        Logs.Configuration.LogError(ex.Message);
                    }
                }
                catch (ConfigException ex)
                {
                    if (!string.IsNullOrEmpty(ex.Message))
                    {
                        Logs.Configuration.LogError(ex.Message);
                    }
                }
                catch (InterruptedConsoleException) { }
                catch (Exception ex)
                {
                    Logs.Configuration.LogError(ex.Message);
                    Logs.Configuration.LogDebug(ex.StackTrace);
                }
            }
        }
        public TumblerClientConfiguration LoadArgs(NetworksSelector networkSet, String[] args)
        {
            ConfigurationFile = args.Where(a => a.StartsWith("-conf=", StringComparison.Ordinal)).Select(a => a.Substring("-conf=".Length).Replace("\"", "")).FirstOrDefault();
            DataDir           = args.Where(a => a.StartsWith("-datadir=", StringComparison.Ordinal)).Select(a => a.Substring("-datadir=".Length).Replace("\"", "")).FirstOrDefault();
            if (DataDir != null && ConfigurationFile != null)
            {
                var isRelativePath = Path.GetFullPath(ConfigurationFile).Length > ConfigurationFile.Length;
                if (isRelativePath)
                {
                    ConfigurationFile = Path.Combine(DataDir, ConfigurationFile);
                }
            }

            Network = args.Contains("-testnet", StringComparer.OrdinalIgnoreCase) ? networkSet.Testnet() :
                      args.Contains("-regtest", StringComparer.OrdinalIgnoreCase) ? networkSet.Regtest() :
                      networkSet.Mainnet();

            if (ConfigurationFile != null)
            {
                AssetConfigFileExists();
                var configTemp = TextFileConfiguration.Parse(File.ReadAllText(ConfigurationFile));
                Network = configTemp.GetOrDefault <bool>("testnet", false) ? networkSet.Testnet() :
                          configTemp.GetOrDefault <bool>("regtest", false) ? networkSet.Regtest() :
                          networkSet.Mainnet();
            }

            if (DataDir == null)
            {
                DataDir = DefaultDataDirectory.GetDefaultDirectory("NTumbleBit", Network);
            }

            if (ConfigurationFile == null)
            {
                ConfigurationFile = GetDefaultConfigurationFile(DataDir, Network);
            }
            Logs.Configuration.LogInformation("Network: " + Network);

            Logs.Configuration.LogInformation("Data directory set to " + DataDir);
            Logs.Configuration.LogInformation("Configuration file set to " + ConfigurationFile);

            if (!Directory.Exists(DataDir))
            {
                throw new ConfigurationException("Data directory does not exists");
            }

            var consoleConfig = new TextFileConfiguration(args);
            var config        = TextFileConfiguration.Parse(File.ReadAllText(ConfigurationFile));

            consoleConfig.MergeInto(config, true);
            config.AddAlias("server", "tumbler.server");

            OnlyMonitor   = config.GetOrDefault <bool>("onlymonitor", false);
            Cooperative   = config.GetOrDefault <bool>("cooperative", true);
            TumblerServer = config.GetOrDefault("tumbler.server", null as TumblerUrlBuilder);
            TorPath       = config.GetOrDefault <string>("torpath", "tor");

            RPCArgs = RPCArgs.Parse(config, Network);

            if (!OnlyMonitor && TumblerServer == null)
            {
                throw new ConfigException("tumbler.server not configured");
            }

            try
            {
                var key = config.GetOrDefault("outputwallet.extpubkey", null as string);
                if (key != null)
                {
                    OutputWallet.RootKey = new BitcoinExtPubKey(key, Network);
                }
            }
            catch
            {
                throw new ConfigException("outputwallet.extpubkey is not configured correctly");
            }

            OutputWallet.KeyPath = new KeyPath("0");
            string keyPathString = config.GetOrDefault("outputwallet.keypath", null as string);

            if (keyPathString != null)
            {
                try
                {
                    OutputWallet.KeyPath = new KeyPath(keyPathString);
                }
                catch
                {
                    throw new ConfigException("outputwallet.keypath is not configured correctly");
                }
            }

            if (OutputWallet.KeyPath.ToString().Contains("'"))
            {
                throw new ConfigException("outputwallet.keypath should not contain any hardened derivation");
            }

            if (OutputWallet.RootKey != null && OutputWallet.RootKey.Network != Network)
            {
                throw new ConfigException("outputwallet.extpubkey is pointing an incorrect network");
            }

            OutputWallet.RPCArgs = RPCArgs.Parse(config, Network, "outputwallet");

            AliceConnectionSettings = ConnectionSettingsBase.ParseConnectionSettings("alice", config);
            BobConnectionSettings   = ConnectionSettingsBase.ParseConnectionSettings("bob", config);

            AllowInsecure = config.GetOrDefault <bool>("allowinsecure", IsTest(Network));
            return(this);
        }
예제 #7
0
        public TumblerConfiguration LoadArgs(NetworksSelector networkSet, String[] args)
        {
            ConfigurationFile = args.Where(a => a.StartsWith("-conf=", StringComparison.Ordinal)).Select(a => a.Substring("-conf=".Length).Replace("\"", "")).FirstOrDefault();
            DataDir           = args.Where(a => a.StartsWith("-datadir=", StringComparison.Ordinal)).Select(a => a.Substring("-datadir=".Length).Replace("\"", "")).FirstOrDefault();
            if (DataDir != null && ConfigurationFile != null)
            {
                var isRelativePath = Path.GetFullPath(ConfigurationFile).Length > ConfigurationFile.Length;
                if (isRelativePath)
                {
                    ConfigurationFile = Path.Combine(DataDir, ConfigurationFile);
                }
            }

            Network = args.Contains("-testnet", StringComparer.OrdinalIgnoreCase) ? networkSet.Testnet() :
                      args.Contains("-regtest", StringComparer.OrdinalIgnoreCase) ? networkSet.Regtest() :
                      networkSet.Mainnet();

            if (ConfigurationFile != null)
            {
                AssetConfigFileExists();
                var configTemp = TextFileConfiguration.Parse(File.ReadAllText(ConfigurationFile));
                Network = configTemp.GetOrDefault <bool>("testnet", false) ? networkSet.Testnet() :
                          configTemp.GetOrDefault <bool>("regtest", false) ? networkSet.Regtest() :
                          networkSet.Mainnet();
            }
            if (DataDir == null)
            {
                DataDir = DefaultDataDirectory.GetDefaultDirectory("NTumbleBitServer", Network);
            }

            if (ConfigurationFile == null)
            {
                ConfigurationFile = GetDefaultConfigurationFile(Network);
            }
            Logs.Configuration.LogInformation("Network: " + Network);

            Logs.Configuration.LogInformation("Data directory set to " + DataDir);
            Logs.Configuration.LogInformation("Configuration file set to " + ConfigurationFile);

            if (!Directory.Exists(DataDir))
            {
                throw new ConfigurationException("Data directory does not exists");
            }

            var consoleConfig = new TextFileConfiguration(args);
            var config        = TextFileConfiguration.Parse(File.ReadAllText(ConfigurationFile));

            consoleConfig.MergeInto(config, true);

            if (config.Contains("help"))
            {
                Console.WriteLine("Details on the wiki page :  https://github.com/NTumbleBit/NTumbleBit/wiki/Server-Config");
                OpenBrowser("https://github.com/NTumbleBit/NTumbleBit/wiki/Server-Config");
                Environment.Exit(0);
            }

            var standardCycles = new StandardCycles(Network);
            var cycleName      = config.GetOrDefault <string>("cycle", standardCycles.Debug ? "shorty2x" : "kotori");

            Logs.Configuration.LogInformation($"Using cycle {cycleName}");

            var standardCycle = standardCycles.GetStandardCycle(cycleName);

            if (standardCycle == null)
            {
                throw new ConfigException($"Invalid cycle name, choose among {String.Join(",", standardCycles.ToEnumerable().Select(c => c.FriendlyName).ToArray())}");
            }

            ClassicTumblerParameters.CycleGenerator = standardCycle.Generator;
            ClassicTumblerParameters.Denomination   = standardCycle.Denomination;
            var torEnabled = config.GetOrDefault <bool>("tor.enabled", true);

            if (torEnabled)
            {
                TorSettings = TorConnectionSettings.ParseConnectionSettings("tor", config);
            }

            Cooperative = config.GetOrDefault <bool>("cooperative", true);

            var defaultPort = config.GetOrDefault <int>("port", 37123);

            OnlyMonitor = config.GetOrDefault <bool>("onlymonitor", false);
            Listen      = new IPEndPoint(IPAddress.Parse("127.0.0.1"), defaultPort);

            RPC = RPCArgs.Parse(config, Network);

            //0.1% fee by default
            var defaultFee = Money.Satoshis((decimal)ClassicTumblerParameters.Denomination.Satoshi * 0.001m);

            ClassicTumblerParameters.Fee = config.GetOrDefault <Money>("tumbler.fee", defaultFee);
            TorPath = config.GetOrDefault <string>("torpath", "tor");
            return(this);
        }