/// <summary> /// Loads the node settings from the application configuration. /// </summary> private void LoadConfiguration() { TextFileConfiguration config = this.ConfigReader; this.MinTxFeeRate = new FeeRate(config.GetOrDefault("mintxfee", this.Network.MinTxFee, this.Logger)); this.FallbackTxFeeRate = new FeeRate(config.GetOrDefault("fallbackfee", this.Network.FallbackFee, this.Logger)); this.MinRelayTxFeeRate = new FeeRate(config.GetOrDefault("minrelaytxfee", this.Network.MinRelayTxFee, this.Logger)); }
/// <summary> /// Loads the configuration file. /// </summary> /// <returns>Initialized node configuration.</returns> /// <exception cref="ConfigurationException">Thrown in case of any problems with the configuration file or command line arguments.</exception> public NodeSettings LoadConfiguration(List <IFeatureRegistration> features = null) { // Configuration already loaded? if (this.ConfigReader != null) { return(this); } // Get the arguments set previously var args = this.LoadArgs; // If no configuration file path is passed in the args, load the default file. if (this.ConfigurationFile == null) { this.ConfigurationFile = this.CreateDefaultConfigurationFile(features); } var consoleConfig = new TextFileConfiguration(args); var config = new TextFileConfiguration(File.ReadAllText(this.ConfigurationFile)); this.ConfigReader = config; consoleConfig.MergeInto(config); if (!Directory.Exists(this.DataFolder.CoinViewPath)) { Directory.CreateDirectory(this.DataFolder.CoinViewPath); } // Set the configuration filter and file path. this.Log.Load(config); this.LoggerFactory.AddFilters(this.Log, this.DataFolder); this.LoggerFactory.ConfigureConsoleFilters(this.LoggerFactory.GetConsoleSettings(), this.Log); this.Logger.LogDebug("Data directory set to '{0}'.", this.DataDir); this.Logger.LogDebug("Configuration file set to '{0}'.", this.ConfigurationFile); this.RequireStandard = config.GetOrDefault("acceptnonstdtxn", !(this.Network.IsTest())); this.MaxTipAge = config.GetOrDefault("maxtipage", this.Network.MaxTipAge); this.Logger.LogDebug("Network: IsTest='{0}', IsBitcoin='{1}'.", this.Network.IsTest(), this.Network.IsBitcoin()); this.MinTxFeeRate = new FeeRate(config.GetOrDefault("mintxfee", this.Network.MinTxFee)); this.Logger.LogDebug("MinTxFeeRate set to {0}.", this.MinTxFeeRate); this.FallbackTxFeeRate = new FeeRate(config.GetOrDefault("fallbackfee", this.Network.FallbackFee)); this.Logger.LogDebug("FallbackTxFeeRate set to {0}.", this.FallbackTxFeeRate); this.MinRelayTxFeeRate = new FeeRate(config.GetOrDefault("minrelaytxfee", this.Network.MinRelayTxFee)); this.Logger.LogDebug("MinRelayTxFeeRate set to {0}.", this.MinRelayTxFeeRate); this.SyncTimeEnabled = config.GetOrDefault <bool>("synctime", true); this.Logger.LogDebug("Time synchronization with peers is {0}.", this.SyncTimeEnabled ? "enabled" : "disabled"); // Add a prefix set by the user to the agent. This will allow people running nodes to // identify themselves if they wish. The prefix is limited to 10 characters. string agentPrefix = config.GetOrDefault("agentprefix", string.Empty); agentPrefix = agentPrefix.Substring(0, Math.Min(10, agentPrefix.Length)); this.Agent = string.IsNullOrEmpty(agentPrefix) ? this.Agent : $"{agentPrefix}-{this.Agent}"; return(this); }
/// <summary> /// Loads the node settings from the application configuration. /// </summary> private void LoadConfiguration() { TextFileConfiguration config = this.ConfigReader; this.RequireStandard = config.GetOrDefault("acceptnonstdtxn", !(this.Network.IsTest())); this.Logger.LogDebug("RequireStandard set to {0}.", this.RequireStandard); this.MaxTipAge = config.GetOrDefault("maxtipage", this.Network.MaxTipAge); this.Logger.LogDebug("MaxTipAge set to {0}.", this.MaxTipAge); this.MinTxFeeRate = new FeeRate(config.GetOrDefault("mintxfee", this.Network.MinTxFee)); this.Logger.LogDebug("MinTxFeeRate set to {0}.", this.MinTxFeeRate); this.FallbackTxFeeRate = new FeeRate(config.GetOrDefault("fallbackfee", this.Network.FallbackFee)); this.Logger.LogDebug("FallbackTxFeeRate set to {0}.", this.FallbackTxFeeRate); this.MinRelayTxFeeRate = new FeeRate(config.GetOrDefault("minrelaytxfee", this.Network.MinRelayTxFee)); this.Logger.LogDebug("MinRelayTxFeeRate set to {0}.", this.MinRelayTxFeeRate); this.SyncTimeEnabled = config.GetOrDefault <bool>("synctime", true); this.Logger.LogDebug("Time synchronization with peers is {0}.", this.SyncTimeEnabled ? "enabled" : "disabled"); string agentPrefix = config.GetOrDefault("agentprefix", string.Empty).Replace("-", ""); if (agentPrefix.Length > MaximumAgentPrefixLength) { agentPrefix = agentPrefix.Substring(0, MaximumAgentPrefixLength); } this.Logger.LogDebug("AgentPrefix set to {0}.", agentPrefix); // Since we are relying on the "this.Agent" value that may have been changed by an earlier call to // this method follow good coding practice and ensure that we always get the same result on subsequent calls. string agent = this.Agent.Substring(this.Agent.IndexOf("-") + 1); this.Agent = string.IsNullOrEmpty(agentPrefix) ? agent : $"{agentPrefix}-{agent}"; this.Logger.LogDebug("Agent set to {0}.", this.Agent); }
/// <summary> /// Initializes a new instance of the object. /// </summary> /// <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> public NodeSettings(Network innerNetwork = null, ProtocolVersion protocolVersion = SupportedProtocolVersion, string agent = "StratisBitcoin", string[] args = null, bool loadConfiguration = true) { this.Agent = agent; this.Network = innerNetwork; this.ProtocolVersion = protocolVersion; this.Log = new LogSettings(); this.LoggerFactory = new ExtendedLoggerFactory(); this.LoggerFactory.AddConsoleWithFilters(); this.LoggerFactory.AddNLog(); this.Logger = this.LoggerFactory.CreateLogger(typeof(NodeSettings).FullName); // Load arguments or configuration from .ctor? this.LoadArgs = args ?? new string[] { }; // 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.LoadArgs.GetValueOf("-conf")?.NormalizeDirectorySeparator(); this.DataDir = this.LoadArgs.GetValueOf("-datadir")?.NormalizeDirectorySeparator(); // 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 network is not known then derive it from the command line arguments if (this.Network == null) { var regTest = false; var testNet = false; // Find out if we need to run on testnet or regtest from the config file. if (this.ConfigurationFile != null) { AssertConfigFileExists(this.ConfigurationFile); var configTemp = new TextFileConfiguration(File.ReadAllText(this.ConfigurationFile)); testNet = configTemp.GetOrDefault <bool>("testnet", false); regTest = configTemp.GetOrDefault <bool>("regtest", false); } // Only if args contains -testnet, do we set it to true, otherwise it overwrites file configuration if (this.LoadArgs.Contains("-testnet", StringComparer.CurrentCultureIgnoreCase)) { testNet = true; } // Only if args contains -regtest, do we set it to true, otherwise it overwrites file configuration if (this.LoadArgs.Contains("-regtest", StringComparer.CurrentCultureIgnoreCase)) { regTest = true; } if (testNet && regTest) { throw new ConfigurationException("Invalid combination of -regtest and -testnet."); } this.Network = testNet ? Network.TestNet : regTest?Network.RegTest : Network.Main; } // Setting the data directory. if (this.DataDir == null) { this.DataDir = this.CreateDefaultDataDirectories(Path.Combine("StratisNode", this.Network.RootFolderName), this.Network); } else { // Create the data directories if they don't exist. string directoryPath = Path.Combine(this.DataDir, this.Network.RootFolderName, this.Network.Name); Directory.CreateDirectory(directoryPath); this.DataDir = directoryPath; this.Logger.LogDebug("Data directory initialized with path {0}.", directoryPath); } this.DataFolder = new DataFolder(this.DataDir); // Load configuration from .ctor? if (loadConfiguration) { this.LoadConfiguration(); } }
/// <summary> /// Initializes configuration from command line arguments. /// <para>This includes loading configuration from file.</para> /// </summary> /// <param name="args">Application command line arguments.</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 NodeSettings LoadArguments(string[] 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 = args.GetValueOf("-conf")?.NormalizeDirectorySeparator(); this.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 (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); } } // Find out if we need to run on testnet or regtest from the config file. if (this.ConfigurationFile != null) { AssertConfigFileExists(this.ConfigurationFile); var configTemp = new TextFileConfiguration(File.ReadAllText(this.ConfigurationFile)); this.Testnet = configTemp.GetOrDefault <bool>("testnet", false); this.RegTest = configTemp.GetOrDefault <bool>("regtest", false); } //Only if args contains -testnet, do we set it to true, otherwise it overwrites file configuration if (args.Contains("-testnet", StringComparer.CurrentCultureIgnoreCase)) { this.Testnet = true; } //Only if args contains -regtest, do we set it to true, otherwise it overwrites file configuration if (args.Contains("-regtest", StringComparer.CurrentCultureIgnoreCase)) { this.RegTest = true; } if (this.Testnet && this.RegTest) { throw new ConfigurationException("Invalid combination of -regtest and -testnet."); } this.Network = this.GetNetwork(); if (this.DataDir == null) { this.DataDir = this.CreateDefaultDataDirectories(Path.Combine("StratisNode", this.Name), this.Network); } if (!Directory.Exists(this.DataDir)) { throw new ConfigurationException($"Data directory {this.DataDir} does not exist."); } // If no configuration file path is passed in the args, load the default file. if (this.ConfigurationFile == null) { this.ConfigurationFile = this.CreateDefaultConfigurationFile(); } var consoleConfig = new TextFileConfiguration(args); var config = new TextFileConfiguration(File.ReadAllText(this.ConfigurationFile)); this.ConfigReader = config; consoleConfig.MergeInto(config); this.DataFolder = new DataFolder(this); if (!Directory.Exists(this.DataFolder.CoinViewPath)) { Directory.CreateDirectory(this.DataFolder.CoinViewPath); } // Set the configuration filter and file path. this.Log.Load(config); this.LoggerFactory.AddFilters(this.Log, this.DataFolder); this.LoggerFactory.ConfigureConsoleFilters(this.LoggerFactory.GetConsoleSettings(), this.Log); this.Logger.LogDebug("Data directory set to '{0}'.", this.DataDir); this.Logger.LogDebug("Configuration file set to '{0}'.", this.ConfigurationFile); this.RequireStandard = config.GetOrDefault("acceptnonstdtxn", !(this.RegTest || this.Testnet)); this.MaxTipAge = config.GetOrDefault("maxtipage", DefaultMaxTipAge); this.ApiUri = config.GetOrDefault("apiuri", new Uri($"http://localhost:{ (this.Network.ToString().StartsWith("Stratis") ? 37221 : 37220) }")); this.Logger.LogDebug("Network: IsTest='{0}', IsBitcoin='{1}'.", this.Network.IsTest(), this.Network.IsBitcoin()); this.MinTxFeeRate = new FeeRate(config.GetOrDefault("mintxfee", this.Network.MinTxFee)); this.Logger.LogDebug("MinTxFeeRate set to {0}.", this.MinTxFeeRate); this.FallbackTxFeeRate = new FeeRate(config.GetOrDefault("fallbackfee", this.Network.FallbackFee)); this.Logger.LogDebug("FallbackTxFeeRate set to {0}.", this.FallbackTxFeeRate); this.MinRelayTxFeeRate = new FeeRate(config.GetOrDefault("minrelaytxfee", this.Network.MinRelayTxFee)); this.Logger.LogDebug("MinRelayTxFeeRate set to {0}.", this.MinRelayTxFeeRate); this.SyncTimeEnabled = config.GetOrDefault <bool>("synctime", true); this.Logger.LogDebug("Time synchronization with peers is {0}.", this.SyncTimeEnabled ? "enabled" : "disabled"); try { this.ConnectionManager.Connect.AddRange(config.GetAll("connect") .Select(c => ConvertIpAddressToEndpoint(c, this.Network.DefaultPort))); } catch (FormatException) { throw new ConfigurationException("Invalid 'connect' parameter."); } try { this.ConnectionManager.AddNode.AddRange(config.GetAll("addnode") .Select(c => ConvertIpAddressToEndpoint(c, this.Network.DefaultPort))); } catch (FormatException) { throw new ConfigurationException("Invalid 'addnode' parameter."); } var port = config.GetOrDefault <int>("port", this.Network.DefaultPort); try { this.ConnectionManager.Listen.AddRange(config.GetAll("bind") .Select(c => new NodeServerEndpoint(ConvertIpAddressToEndpoint(c, port), false))); } catch (FormatException) { throw new ConfigurationException("Invalid 'bind' parameter"); } try { this.ConnectionManager.Listen.AddRange(config.GetAll("whitebind") .Select(c => new NodeServerEndpoint(ConvertIpAddressToEndpoint(c, port), true))); } catch (FormatException) { throw new ConfigurationException("Invalid 'listen' parameter"); } if (this.ConnectionManager.Listen.Count == 0) { this.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 { this.ConnectionManager.ExternalEndpoint = ConvertIpAddressToEndpoint(externalIp, port); } catch (FormatException) { throw new ConfigurationException("Invalid 'externalip' parameter"); } } if (this.ConnectionManager.ExternalEndpoint == null) { this.ConnectionManager.ExternalEndpoint = new IPEndPoint(IPAddress.Loopback, this.Network.DefaultPort); } this.ConnectionManager.BanTimeSeconds = config.GetOrDefault <int>("bantime", ConnectionManagerSettings.DefaultMisbehavingBantimeSeconds); return(this); }
/// <summary> /// Loads the configuration file. /// </summary> /// <returns>Initialized node configuration.</returns> /// <exception cref="ConfigurationException">Thrown in case of any problems with the configuration file or command line arguments.</exception> public NodeSettings LoadConfiguration() { // Configuration already loaded? if (this.ConfigReader != null) { return(this); } // Get the arguments set previously var args = this.LoadArgs; // Setting the data directory. if (this.DataDir == null) { this.DataDir = this.CreateDefaultDataDirectories(Path.Combine("StratisNode", this.Network.RootFolderName), this.Network); } else { // Create the data directories if they don't exist. string directoryPath = Path.Combine(this.DataDir, this.Network.RootFolderName, this.Network.Name); Directory.CreateDirectory(directoryPath); this.DataDir = directoryPath; this.Logger.LogDebug("Data directory initialized with path {0}.", directoryPath); } // If no configuration file path is passed in the args, load the default file. if (this.ConfigurationFile == null) { this.ConfigurationFile = this.CreateDefaultConfigurationFile(); } var consoleConfig = new TextFileConfiguration(args); var config = new TextFileConfiguration(File.ReadAllText(this.ConfigurationFile)); this.ConfigReader = config; consoleConfig.MergeInto(config); this.DataFolder = new DataFolder(this.DataDir); if (!Directory.Exists(this.DataFolder.CoinViewPath)) { Directory.CreateDirectory(this.DataFolder.CoinViewPath); } // Set the configuration filter and file path. this.Log.Load(config); this.LoggerFactory.AddFilters(this.Log, this.DataFolder); this.LoggerFactory.ConfigureConsoleFilters(this.LoggerFactory.GetConsoleSettings(), this.Log); this.Logger.LogDebug("Data directory set to '{0}'.", this.DataDir); this.Logger.LogDebug("Configuration file set to '{0}'.", this.ConfigurationFile); this.RequireStandard = config.GetOrDefault("acceptnonstdtxn", !(this.Network.IsTest())); this.MaxTipAge = config.GetOrDefault("maxtipage", this.Network.MaxTipAge); this.Logger.LogDebug("Network: IsTest='{0}', IsBitcoin='{1}'.", this.Network.IsTest(), this.Network.IsBitcoin()); this.MinTxFeeRate = new FeeRate(config.GetOrDefault("mintxfee", this.Network.MinTxFee)); this.Logger.LogDebug("MinTxFeeRate set to {0}.", this.MinTxFeeRate); this.FallbackTxFeeRate = new FeeRate(config.GetOrDefault("fallbackfee", this.Network.FallbackFee)); this.Logger.LogDebug("FallbackTxFeeRate set to {0}.", this.FallbackTxFeeRate); this.MinRelayTxFeeRate = new FeeRate(config.GetOrDefault("minrelaytxfee", this.Network.MinRelayTxFee)); this.Logger.LogDebug("MinRelayTxFeeRate set to {0}.", this.MinRelayTxFeeRate); this.SyncTimeEnabled = config.GetOrDefault <bool>("synctime", true); this.Logger.LogDebug("Time synchronization with peers is {0}.", this.SyncTimeEnabled ? "enabled" : "disabled"); return(this); }
/// <summary> /// Initializes configuration from command line arguments. /// <para>This includes loading configuration from file.</para> /// </summary> /// <param name="args">Application command line arguments.</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 NodeSettings LoadArguments(string[] 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 = args.GetValueOf("-conf")?.NormalizeDirectorySeparator(); var 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 (dataDir != null && this.ConfigurationFile != null) { bool isRelativePath = Path.GetFullPath(this.ConfigurationFile).Length > this.ConfigurationFile.Length; if (isRelativePath) { this.ConfigurationFile = Path.Combine(dataDir, this.ConfigurationFile); } } // Find out if we need to run on testnet or regtest from the config file. if (this.ConfigurationFile != null) { AssertConfigFileExists(this.ConfigurationFile); var configTemp = new TextFileConfiguration(File.ReadAllText(this.ConfigurationFile)); this.Testnet = configTemp.GetOrDefault <bool>("testnet", false); this.RegTest = configTemp.GetOrDefault <bool>("regtest", false); } //Only if args contains -testnet, do we set it to true, otherwise it overwrites file configuration if (args.Contains("-testnet", StringComparer.CurrentCultureIgnoreCase)) { this.Testnet = true; } //Only if args contains -regtest, do we set it to true, otherwise it overwrites file configuration if (args.Contains("-regtest", StringComparer.CurrentCultureIgnoreCase)) { this.RegTest = true; } if (this.Testnet && this.RegTest) { throw new ConfigurationException("Invalid combination of -regtest and -testnet."); } this.Network = this.GetNetwork(); // Setting the data directory. if (dataDir == null) { this.DataDir = this.CreateDefaultDataDirectories(Path.Combine("StratisNode", this.Network.RootFolderName), this.Network); } else { // Create the data directories if they don't exist. string directoryPath = Path.Combine(dataDir, this.Network.RootFolderName, this.Network.Name); Directory.CreateDirectory(directoryPath); this.DataDir = directoryPath; this.Logger.LogDebug("Data directory initialized with path {0}.", directoryPath); } // If no configuration file path is passed in the args, load the default file. if (this.ConfigurationFile == null) { this.ConfigurationFile = this.CreateDefaultConfigurationFile(); } var consoleConfig = new TextFileConfiguration(args); var config = new TextFileConfiguration(File.ReadAllText(this.ConfigurationFile)); this.ConfigReader = config; consoleConfig.MergeInto(config); this.DataFolder = new DataFolder(this.DataDir); if (!Directory.Exists(this.DataFolder.CoinViewPath)) { Directory.CreateDirectory(this.DataFolder.CoinViewPath); } // Set the configuration filter and file path. this.Log.Load(config); this.LoggerFactory.AddFilters(this.Log, this.DataFolder); this.LoggerFactory.ConfigureConsoleFilters(this.LoggerFactory.GetConsoleSettings(), this.Log); this.Logger.LogDebug("Data directory set to '{0}'.", this.DataDir); this.Logger.LogDebug("Configuration file set to '{0}'.", this.ConfigurationFile); this.RequireStandard = config.GetOrDefault("acceptnonstdtxn", !(this.RegTest || this.Testnet)); this.MaxTipAge = config.GetOrDefault("maxtipage", DefaultMaxTipAge); this.Logger.LogDebug("Network: IsTest='{0}', IsBitcoin='{1}'.", this.Network.IsTest(), this.Network.IsBitcoin()); this.MinTxFeeRate = new FeeRate(config.GetOrDefault("mintxfee", this.Network.MinTxFee)); this.Logger.LogDebug("MinTxFeeRate set to {0}.", this.MinTxFeeRate); this.FallbackTxFeeRate = new FeeRate(config.GetOrDefault("fallbackfee", this.Network.FallbackFee)); this.Logger.LogDebug("FallbackTxFeeRate set to {0}.", this.FallbackTxFeeRate); this.MinRelayTxFeeRate = new FeeRate(config.GetOrDefault("minrelaytxfee", this.Network.MinRelayTxFee)); this.Logger.LogDebug("MinRelayTxFeeRate set to {0}.", this.MinRelayTxFeeRate); this.SyncTimeEnabled = config.GetOrDefault <bool>("synctime", true); this.Logger.LogDebug("Time synchronization with peers is {0}.", this.SyncTimeEnabled ? "enabled" : "disabled"); return(this); }