/// <summary> /// Initializes configuration from command line arguments. /// <para>This includes loading configuration from file.</para> /// </summary> /// <param name="args">Application command line arguments.</param> /// <param name="name">Blockchain name. Currently only "bitcoin" and "stratis" are used.</param> /// <param name="innerNetwork">Specification of the network the node runs on - regtest/testnet/mainnet.</param> /// <param name="protocolVersion">Supported protocol version for which to create the configuration.</param> /// <returns>Initialized node configuration.</returns> /// <exception cref="ConfigurationException">Thrown in case of any problems with the configuration file or command line arguments.</exception> public static NodeSettings FromArguments(string[] args, string name = "bitcoin", Network innerNetwork = null, ProtocolVersion protocolVersion = SupportedProtocolVersion) { if (string.IsNullOrEmpty(name)) { throw new ConfigurationException("A network name is mandatory"); } NodeSettings nodeSettings = new NodeSettings { Name = name }; // The logger factory goes in the settings with minimal configuration, // that's so the settings can also log out its progress. nodeSettings.LoggerFactory.AddConsoleWithFilters(out ConsoleLoggerSettings consoleSettings); nodeSettings.LoggerFactory.AddNLog(); nodeSettings.Logger = nodeSettings.LoggerFactory.CreateLogger(typeof(NodeSettings).FullName); if (innerNetwork != null) { nodeSettings.Network = innerNetwork; } nodeSettings.ProtocolVersion = protocolVersion; nodeSettings.ConfigurationFile = args.GetValueOf("-conf"); nodeSettings.DataDir = args.GetValueOf("-datadir"); if (nodeSettings.DataDir != null && nodeSettings.ConfigurationFile != null) { bool isRelativePath = Path.GetFullPath(nodeSettings.ConfigurationFile).Length > nodeSettings.ConfigurationFile.Length; if (isRelativePath) { nodeSettings.ConfigurationFile = Path.Combine(nodeSettings.DataDir, nodeSettings.ConfigurationFile); } } nodeSettings.Testnet = args.Contains("-testnet", StringComparer.CurrentCultureIgnoreCase); nodeSettings.RegTest = args.Contains("-regtest", StringComparer.CurrentCultureIgnoreCase); if (nodeSettings.ConfigurationFile != null) { AssertConfigFileExists(nodeSettings); var configTemp = TextFileConfiguration.Parse(File.ReadAllText(nodeSettings.ConfigurationFile)); nodeSettings.Testnet = configTemp.GetOrDefault <bool>("testnet", false); nodeSettings.RegTest = configTemp.GetOrDefault <bool>("regtest", false); } if (nodeSettings.Testnet && nodeSettings.RegTest) { throw new ConfigurationException("Invalid combination of -regtest and -testnet"); } nodeSettings.Network = nodeSettings.GetNetwork(); if (nodeSettings.DataDir == null) { nodeSettings.SetDefaultDataDir(Path.Combine("StratisNode", nodeSettings.Name), nodeSettings.Network); } if (!Directory.Exists(nodeSettings.DataDir)) { throw new ConfigurationException("Data directory does not exists"); } if (nodeSettings.ConfigurationFile == null) { nodeSettings.ConfigurationFile = nodeSettings.GetDefaultConfigurationFile(); } var consoleConfig = new TextFileConfiguration(args); var config = TextFileConfiguration.Parse(File.ReadAllText(nodeSettings.ConfigurationFile)); consoleConfig.MergeInto(config); nodeSettings.DataFolder = new DataFolder(nodeSettings); if (!Directory.Exists(nodeSettings.DataFolder.CoinViewPath)) { Directory.CreateDirectory(nodeSettings.DataFolder.CoinViewPath); } // set the configuration filter and file path nodeSettings.Log.Load(config); nodeSettings.LoggerFactory.AddFilters(nodeSettings.Log, nodeSettings.DataFolder); nodeSettings.LoggerFactory.ConfigureConsoleFilters(consoleSettings, nodeSettings.Log); nodeSettings.Logger.LogInformation("Data directory set to " + nodeSettings.DataDir); nodeSettings.Logger.LogInformation("Configuration file set to " + nodeSettings.ConfigurationFile); nodeSettings.RequireStandard = config.GetOrDefault("acceptnonstdtxn", !(nodeSettings.RegTest || nodeSettings.Testnet)); nodeSettings.MaxTipAge = config.GetOrDefault("maxtipage", DefaultMaxTipAge); nodeSettings.ApiUri = config.GetOrDefault("apiuri", new Uri("http://localhost:5000")); nodeSettings.RPC = config.GetOrDefault <bool>("server", false) ? new RpcSettings() : null; if (nodeSettings.RPC != null) { nodeSettings.RPC.RpcUser = config.GetOrDefault <string>("rpcuser", null); nodeSettings.RPC.RpcPassword = config.GetOrDefault <string>("rpcpassword", null); if (nodeSettings.RPC.RpcPassword == null && nodeSettings.RPC.RpcUser != null) { throw new ConfigurationException("rpcpassword should be provided"); } if (nodeSettings.RPC.RpcUser == null && nodeSettings.RPC.RpcPassword != null) { throw new ConfigurationException("rpcuser should be provided"); } var defaultPort = config.GetOrDefault <int>("rpcport", nodeSettings.Network.RPCPort); nodeSettings.RPC.RPCPort = defaultPort; try { nodeSettings.RPC.Bind = config .GetAll("rpcbind") .Select(p => ConvertToEndpoint(p, defaultPort)) .ToList(); } catch (FormatException) { throw new ConfigurationException("Invalid rpcbind value"); } try { nodeSettings.RPC.AllowIp = config .GetAll("rpcallowip") .Select(p => IPAddress.Parse(p)) .ToList(); } catch (FormatException) { throw new ConfigurationException("Invalid rpcallowip value"); } if (nodeSettings.RPC.AllowIp.Count == 0) { nodeSettings.RPC.Bind.Clear(); nodeSettings.RPC.Bind.Add(new IPEndPoint(IPAddress.Parse("::1"), defaultPort)); nodeSettings.RPC.Bind.Add(new IPEndPoint(IPAddress.Parse("127.0.0.1"), defaultPort)); if (config.Contains("rpcbind")) { nodeSettings.Logger.LogWarning("WARNING: option -rpcbind was ignored because -rpcallowip was not specified, refusing to allow everyone to connect"); } } if (nodeSettings.RPC.Bind.Count == 0) { nodeSettings.RPC.Bind.Add(new IPEndPoint(IPAddress.Parse("::"), defaultPort)); nodeSettings.RPC.Bind.Add(new IPEndPoint(IPAddress.Parse("0.0.0.0"), defaultPort)); } } try { nodeSettings.ConnectionManager.Connect.AddRange(config.GetAll("connect") .Select(c => ConvertToEndpoint(c, nodeSettings.Network.DefaultPort))); } catch (FormatException) { throw new ConfigurationException("Invalid connect parameter"); } try { nodeSettings.ConnectionManager.AddNode.AddRange(config.GetAll("addnode") .Select(c => ConvertToEndpoint(c, nodeSettings.Network.DefaultPort))); } catch (FormatException) { throw new ConfigurationException("Invalid addnode parameter"); } var port = config.GetOrDefault <int>("port", nodeSettings.Network.DefaultPort); try { nodeSettings.ConnectionManager.Listen.AddRange(config.GetAll("listen") .Select(c => new NodeServerEndpoint(ConvertToEndpoint(c, port), false))); } catch (FormatException) { throw new ConfigurationException("Invalid listen parameter"); } try { nodeSettings.ConnectionManager.Listen.AddRange(config.GetAll("whitebind") .Select(c => new NodeServerEndpoint(ConvertToEndpoint(c, port), true))); } catch (FormatException) { throw new ConfigurationException("Invalid listen parameter"); } if (nodeSettings.ConnectionManager.Listen.Count == 0) { nodeSettings.ConnectionManager.Listen.Add(new NodeServerEndpoint(new IPEndPoint(IPAddress.Parse("0.0.0.0"), port), false)); } var externalIp = config.GetOrDefault <string>("externalip", null); if (externalIp != null) { try { nodeSettings.ConnectionManager.ExternalEndpoint = ConvertToEndpoint(externalIp, port); } catch (FormatException) { throw new ConfigurationException("Invalid externalip parameter"); } } if (nodeSettings.ConnectionManager.ExternalEndpoint == null) { nodeSettings.ConnectionManager.ExternalEndpoint = new IPEndPoint(IPAddress.Loopback, nodeSettings.Network.DefaultPort); } nodeSettings.Mempool.Load(config); nodeSettings.Store.Load(config); return(nodeSettings); }
/// <summary> /// Initializes configuration from command line arguments. /// <para>This includes loading configuration from file.</para> /// </summary> /// <param name="args">Application command line arguments.</param> /// <param name="name">Blockchain name. Currently only "bitcoin" and "stratis" are used.</param> /// <param name="innerNetwork">Specification of 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> /// <returns>Initialized node configuration.</returns> /// <exception cref="ConfigurationException">Thrown in case of any problems with the configuration file or command line arguments.</exception> public static NodeSettings FromArguments(string[] args, string name = "bitcoin", Network innerNetwork = null, ProtocolVersion protocolVersion = SupportedProtocolVersion, string agent = "StratisBitcoin") { if (string.IsNullOrEmpty(name)) { throw new ConfigurationException("A network name is mandatory"); } NodeSettings nodeSettings = new NodeSettings { Name = name, Agent = agent }; // The logger factory goes in the settings with minimal configuration, // that's so the settings can also log out its progress. nodeSettings.LoggerFactory.AddConsoleWithFilters(out ConsoleLoggerSettings consoleSettings); nodeSettings.LoggerFactory.AddNLog(); nodeSettings.Logger = nodeSettings.LoggerFactory.CreateLogger(typeof(NodeSettings).FullName); if (innerNetwork != null) { nodeSettings.Network = innerNetwork; } nodeSettings.ProtocolVersion = protocolVersion; nodeSettings.ConfigurationFile = args.GetValueOf("-conf")?.NormalizeDirectorySeparator(); nodeSettings.DataDir = args.GetValueOf("-datadir")?.NormalizeDirectorySeparator(); // If the configuration file is relative then assume it is relative to the data folder and combine the paths if (nodeSettings.DataDir != null && nodeSettings.ConfigurationFile != null) { bool isRelativePath = Path.GetFullPath(nodeSettings.ConfigurationFile).Length > nodeSettings.ConfigurationFile.Length; if (isRelativePath) { nodeSettings.ConfigurationFile = Path.Combine(nodeSettings.DataDir, nodeSettings.ConfigurationFile); } } nodeSettings.Testnet = args.Contains("-testnet", StringComparer.CurrentCultureIgnoreCase); nodeSettings.RegTest = args.Contains("-regtest", StringComparer.CurrentCultureIgnoreCase); if (nodeSettings.ConfigurationFile != null) { AssertConfigFileExists(nodeSettings); var configTemp = TextFileConfiguration.Parse(File.ReadAllText(nodeSettings.ConfigurationFile)); nodeSettings.Testnet = configTemp.GetOrDefault <bool>("testnet", false); nodeSettings.RegTest = configTemp.GetOrDefault <bool>("regtest", false); } if (nodeSettings.Testnet && nodeSettings.RegTest) { throw new ConfigurationException("Invalid combination of -regtest and -testnet"); } nodeSettings.Network = nodeSettings.GetNetwork(); if (nodeSettings.DataDir == null) { nodeSettings.SetDefaultDataDir(Path.Combine("StratisNode", nodeSettings.Name), nodeSettings.Network); } if (!Directory.Exists(nodeSettings.DataDir)) { throw new ConfigurationException("Data directory does not exists"); } if (nodeSettings.ConfigurationFile == null) { nodeSettings.ConfigurationFile = nodeSettings.GetDefaultConfigurationFile(); } var consoleConfig = new TextFileConfiguration(args); var config = TextFileConfiguration.Parse(File.ReadAllText(nodeSettings.ConfigurationFile)); nodeSettings.ConfigReader = config; consoleConfig.MergeInto(config); nodeSettings.DataFolder = new DataFolder(nodeSettings); if (!Directory.Exists(nodeSettings.DataFolder.CoinViewPath)) { Directory.CreateDirectory(nodeSettings.DataFolder.CoinViewPath); } // Set the configuration filter and file path. nodeSettings.Log.Load(config); nodeSettings.LoggerFactory.AddFilters(nodeSettings.Log, nodeSettings.DataFolder); nodeSettings.LoggerFactory.ConfigureConsoleFilters(consoleSettings, nodeSettings.Log); nodeSettings.Logger.LogInformation("Data directory set to '{0}'.", nodeSettings.DataDir); nodeSettings.Logger.LogInformation("Configuration file set to '{0}'.", nodeSettings.ConfigurationFile); nodeSettings.RequireStandard = config.GetOrDefault("acceptnonstdtxn", !(nodeSettings.RegTest || nodeSettings.Testnet)); nodeSettings.MaxTipAge = config.GetOrDefault("maxtipage", DefaultMaxTipAge); nodeSettings.ApiUri = config.GetOrDefault("apiuri", new Uri("http://localhost:37220")); nodeSettings.Logger.LogDebug("Network: IsTest='{0}', IsBitcoin='{1}'", nodeSettings.Network.IsTest(), nodeSettings.Network.IsBitcoin()); nodeSettings.MinTxFeeRate = new FeeRate(config.GetOrDefault("mintxfee", nodeSettings.Network.MinTxFee)); nodeSettings.Logger.LogDebug("MinTxFeeRate set to {0}.", nodeSettings.MinTxFeeRate); nodeSettings.FallbackTxFeeRate = new FeeRate(config.GetOrDefault("fallbackfee", nodeSettings.Network.FallbackFee)); nodeSettings.Logger.LogDebug("FallbackTxFeeRate set to {0}.", nodeSettings.FallbackTxFeeRate); nodeSettings.MinRelayTxFeeRate = new FeeRate(config.GetOrDefault("minrelaytxfee", nodeSettings.Network.MinRelayTxFee)); nodeSettings.Logger.LogDebug("MinRelayTxFeeRate set to {0}.", nodeSettings.MinRelayTxFeeRate); nodeSettings.SyncTimeEnabled = config.GetOrDefault <bool>("synctime", true); nodeSettings.Logger.LogDebug("Time synchronization with peers is {0}.", nodeSettings.SyncTimeEnabled ? "enabled" : "disabled"); try { nodeSettings.ConnectionManager.Connect.AddRange(config.GetAll("connect") .Select(c => ConvertToEndpoint(c, nodeSettings.Network.DefaultPort))); } catch (FormatException) { throw new ConfigurationException("Invalid connect parameter"); } try { nodeSettings.ConnectionManager.AddNode.AddRange(config.GetAll("addnode") .Select(c => ConvertToEndpoint(c, nodeSettings.Network.DefaultPort))); } catch (FormatException) { throw new ConfigurationException("Invalid addnode parameter"); } var port = config.GetOrDefault <int>("port", nodeSettings.Network.DefaultPort); try { nodeSettings.ConnectionManager.Listen.AddRange(config.GetAll("bind") .Select(c => new NodeServerEndpoint(ConvertToEndpoint(c, port), false))); } catch (FormatException) { throw new ConfigurationException("Invalid bind parameter"); } try { nodeSettings.ConnectionManager.Listen.AddRange(config.GetAll("whitebind") .Select(c => new NodeServerEndpoint(ConvertToEndpoint(c, port), true))); } catch (FormatException) { throw new ConfigurationException("Invalid listen parameter"); } if (nodeSettings.ConnectionManager.Listen.Count == 0) { nodeSettings.ConnectionManager.Listen.Add(new NodeServerEndpoint(new IPEndPoint(IPAddress.Parse("0.0.0.0"), port), false)); } var externalIp = config.GetOrDefault <string>("externalip", null); if (externalIp != null) { try { nodeSettings.ConnectionManager.ExternalEndpoint = ConvertToEndpoint(externalIp, port); } catch (FormatException) { throw new ConfigurationException("Invalid externalip parameter"); } } if (nodeSettings.ConnectionManager.ExternalEndpoint == null) { nodeSettings.ConnectionManager.ExternalEndpoint = new IPEndPoint(IPAddress.Loopback, nodeSettings.Network.DefaultPort); } return(nodeSettings); }