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()); } } }
public UiNodeSettings( Network network = null, ProtocolVersion protocolVersion = SupportedProtocolVersion, string agent = "StratisNode", string[] args = null, NetworksSelector networksSelector = null) : base( network, protocolVersion, agent, args, networksSelector) { }
/// <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(); }
/// <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)); } }
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); }
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); }