Exemplo n.º 1
0
        /// <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));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Reads the configuration file and merges it with the command line arguments.
        /// </summary>
        private void ReadConfigurationFile()
        {
            this.Logger.LogDebug("Reading configuration file '{0}'.", this.ConfigurationFile);

            // Add the file configuration to the command-line configuration.
            var fileConfig = new TextFileConfiguration(File.ReadAllText(this.ConfigurationFile));

            fileConfig.MergeInto(this.ConfigReader);
        }
Exemplo n.º 3
0
        /// <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);
        }
Exemplo n.º 4
0
 /// <summary>
 /// Merges current instance of the configuration to the target instance.
 /// </summary>
 /// <param name="destination">Target instance to merge current instance into.</param>
 public void MergeInto(TextFileConfiguration destination)
 {
     foreach (KeyValuePair <string, List <string> > kv in this.args)
     {
         foreach (string v in kv.Value)
         {
             destination.Add(kv.Key, v);
         }
     }
 }
Exemplo n.º 5
0
 public void MergeInto(TextFileConfiguration destination)
 {
     foreach (var kv in this._Args)
     {
         foreach (var v in kv.Value)
         {
             destination.Add(kv.Key, v);
         }
     }
 }
Exemplo n.º 6
0
        /// <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);
        }
Exemplo n.º 7
0
        /// <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);
        }
Exemplo n.º 10
0
        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
            };

            if (innernetwork != null)
            {
                nodeSettings.Network = innernetwork;
            }

            nodeSettings.ProtocolVersion = protocolVersion;

            nodeSettings.ConfigurationFile = args.Where(a => a.StartsWith("-conf=")).Select(a => a.Substring("-conf=".Length).Replace("\"", "")).FirstOrDefault();
            nodeSettings.DataDir           = args.Where(a => a.StartsWith("-datadir=")).Select(a => a.Substring("-datadir=".Length).Replace("\"", "")).FirstOrDefault();
            if (nodeSettings.DataDir != null && nodeSettings.ConfigurationFile != null)
            {
                var 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)
            {
                AssetConfigFileExists(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.DataDir = GetDefaultDataDir($"stratis{nodeSettings.Name}", nodeSettings.Network);
            }

            if (nodeSettings.ConfigurationFile == null)
            {
                nodeSettings.ConfigurationFile = nodeSettings.GetDefaultConfigurationFile();
            }

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

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

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

            consoleConfig.MergeInto(config);

            nodeSettings.RequireStandard = config.GetOrDefault("acceptnonstdtxn", !(nodeSettings.RegTest || nodeSettings.Testnet));
            nodeSettings.MaxTipAge       = config.GetOrDefault("maxtipage", DEFAULT_MAX_TIP_AGE);

            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"))
                    {
                        Logs.Configuration.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);

            var folder = new DataFolder(nodeSettings);

            if (!Directory.Exists(folder.CoinViewPath))
            {
                Directory.CreateDirectory(folder.CoinViewPath);
            }
            return(nodeSettings);
        }
Exemplo n.º 11
0
        /// <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);
        }
Exemplo n.º 12
0
        /// <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);
        }
Exemplo n.º 13
0
        /// <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);
        }