Commit 9dbe274d authored by Alexey's avatar Alexey

LoadConfiguration method of NodeSettings class has been overridden

parent 7c8e5de2
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\DeStream.Stratis.Bitcoin\DeStream.Stratis.Bitcoin.csproj" />
<ProjectReference Include="..\NBitcoin\NBitcoin.csproj" /> <ProjectReference Include="..\NBitcoin\NBitcoin.csproj" />
<ProjectReference Include="..\Stratis.Bitcoin.Features.Api\Stratis.Bitcoin.Features.Api.csproj" /> <ProjectReference Include="..\Stratis.Bitcoin.Features.Api\Stratis.Bitcoin.Features.Api.csproj" />
<ProjectReference Include="..\Stratis.Bitcoin.Features.LightWallet\Stratis.Bitcoin.Features.LightWallet.csproj" /> <ProjectReference Include="..\Stratis.Bitcoin.Features.LightWallet\Stratis.Bitcoin.Features.LightWallet.csproj" />
......
...@@ -11,6 +11,8 @@ using Stratis.Bitcoin.Features.LightWallet; ...@@ -11,6 +11,8 @@ using Stratis.Bitcoin.Features.LightWallet;
using Stratis.Bitcoin.Features.Notifications; using Stratis.Bitcoin.Features.Notifications;
using Stratis.Bitcoin.Utilities; using Stratis.Bitcoin.Utilities;
using DeStream.Stratis.Bitcoin.Configuration;
namespace DeStream.BreezeD namespace DeStream.BreezeD
{ {
public class Program public class Program
...@@ -30,16 +32,16 @@ namespace DeStream.BreezeD ...@@ -30,16 +32,16 @@ namespace DeStream.BreezeD
var agent = "Breeze"; var agent = "Breeze";
NodeSettings nodeSettings; DeStreamNodeSettings nodeSettings;
if (isDeStream) if (isDeStream)
{ {
Network network = isTestNet ? Network.DeStreamTest : Network.DeStreamMain; Network network = isTestNet ? Network.DeStreamTest : Network.DeStreamMain;
nodeSettings = new NodeSettings(network, ProtocolVersion.ALT_PROTOCOL_VERSION, agent, args:args, loadConfiguration:false); nodeSettings = new DeStreamNodeSettings(network, ProtocolVersion.ALT_PROTOCOL_VERSION, agent, args:args, loadConfiguration:false);
} }
else else
{ {
nodeSettings = new NodeSettings(agent: agent, args: args, loadConfiguration:false); nodeSettings = new DeStreamNodeSettings(agent: agent, args: args, loadConfiguration:false);
} }
IFullNodeBuilder fullNodeBuilder = new FullNodeBuilder() IFullNodeBuilder fullNodeBuilder = new FullNodeBuilder()
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\DeStream.Stratis.Bitcoin\DeStream.Stratis.Bitcoin.csproj" />
<ProjectReference Include="..\NBitcoin\NBitcoin.csproj" /> <ProjectReference Include="..\NBitcoin\NBitcoin.csproj" />
<ProjectReference Include="..\Stratis.Bitcoin.Features.Api\Stratis.Bitcoin.Features.Api.csproj" /> <ProjectReference Include="..\Stratis.Bitcoin.Features.Api\Stratis.Bitcoin.Features.Api.csproj" />
<ProjectReference Include="..\Stratis.Bitcoin.Features.BlockStore\Stratis.Bitcoin.Features.BlockStore.csproj" /> <ProjectReference Include="..\Stratis.Bitcoin.Features.BlockStore\Stratis.Bitcoin.Features.BlockStore.csproj" />
......
...@@ -15,6 +15,8 @@ using Stratis.Bitcoin.Features.RPC; ...@@ -15,6 +15,8 @@ using Stratis.Bitcoin.Features.RPC;
using Stratis.Bitcoin.Features.Wallet; using Stratis.Bitcoin.Features.Wallet;
using Stratis.Bitcoin.Utilities; using Stratis.Bitcoin.Utilities;
using DeStream.Stratis.Bitcoin.Configuration;
namespace DeStream.DeStreamD namespace DeStream.DeStreamD
{ {
public class Program public class Program
...@@ -33,7 +35,7 @@ namespace DeStream.DeStreamD ...@@ -33,7 +35,7 @@ namespace DeStream.DeStreamD
network = Network.DeStreamTest; network = Network.DeStreamTest;
else else
network = Network.DeStreamMain; network = Network.DeStreamMain;
NodeSettings nodeSettings = new NodeSettings(network, ProtocolVersion.ALT_PROTOCOL_VERSION, args:args, loadConfiguration:false); DeStreamNodeSettings nodeSettings = new DeStreamNodeSettings(network, ProtocolVersion.ALT_PROTOCOL_VERSION, args:args, loadConfiguration:false);
Console.WriteLine($"current network: {network.Name}"); Console.WriteLine($"current network: {network.Name}");
......
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\DeStream.Stratis.Bitcoin\DeStream.Stratis.Bitcoin.csproj" />
<ProjectReference Include="..\NBitcoin\NBitcoin.csproj" />
<ProjectReference Include="..\Stratis.Bitcoin.Features.RPC\Stratis.Bitcoin.Features.RPC.csproj" />
<ProjectReference Include="..\Stratis.Bitcoin\Stratis.Bitcoin.csproj" />
</ItemGroup>
</Project>
This diff is collapsed.
{
"profiles": {
"Stratis.CLI Stratis REST API": {
"commandName": "Project",
"commandLineArgs": "stratis Wallet/files"
},
"Stratis.CLI Stratis RPC": {
"commandName": "Project",
"commandLineArgs": "stratis -rpcuser=stratistestuser -rpcpassword=stratistestpass -rpcport=26174 getinfo"
},
"Stratis.CLI Bitcoin RPC": {
"commandName": "Project",
"commandLineArgs": "bitcoin -rpcuser=btctestuser -rpcpassword=btctestpass getbalance"
}
}
}
...@@ -93,6 +93,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeStream.DeStreamD", "DeStr ...@@ -93,6 +93,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeStream.DeStreamD", "DeStr
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeStream.BreezeD", "DeStream.BreezeD\DeStream.BreezeD.csproj", "{5303E8B0-C422-4D1C-8096-24DF6AF75E31}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeStream.BreezeD", "DeStream.BreezeD\DeStream.BreezeD.csproj", "{5303E8B0-C422-4D1C-8096-24DF6AF75E31}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeStream.Stratis.Bitcoin", "DeStream.Stratis.Bitcoin\DeStream.Stratis.Bitcoin.csproj", "{CFE3D6A4-8B4F-4466-984B-74909ED2DA20}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeStream.Stratis.Bitcoin.Cli", "DeStream.Stratis.Bitcoin.Cli\DeStream.Stratis.Bitcoin.Cli.csproj", "{79B71F10-9B43-45C2-ADA4-A84324810D5C}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
...@@ -235,6 +239,14 @@ Global ...@@ -235,6 +239,14 @@ Global
{5303E8B0-C422-4D1C-8096-24DF6AF75E31}.Debug|Any CPU.Build.0 = Debug|Any CPU {5303E8B0-C422-4D1C-8096-24DF6AF75E31}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5303E8B0-C422-4D1C-8096-24DF6AF75E31}.Release|Any CPU.ActiveCfg = Release|Any CPU {5303E8B0-C422-4D1C-8096-24DF6AF75E31}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5303E8B0-C422-4D1C-8096-24DF6AF75E31}.Release|Any CPU.Build.0 = Release|Any CPU {5303E8B0-C422-4D1C-8096-24DF6AF75E31}.Release|Any CPU.Build.0 = Release|Any CPU
{CFE3D6A4-8B4F-4466-984B-74909ED2DA20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CFE3D6A4-8B4F-4466-984B-74909ED2DA20}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CFE3D6A4-8B4F-4466-984B-74909ED2DA20}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CFE3D6A4-8B4F-4466-984B-74909ED2DA20}.Release|Any CPU.Build.0 = Release|Any CPU
{79B71F10-9B43-45C2-ADA4-A84324810D5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{79B71F10-9B43-45C2-ADA4-A84324810D5C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{79B71F10-9B43-45C2-ADA4-A84324810D5C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{79B71F10-9B43-45C2-ADA4-A84324810D5C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
......
using System;
using System.IO;
using Microsoft.Extensions.Logging;
using NBitcoin;
using NBitcoin.Protocol;
using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Utilities;
using Stratis.Bitcoin.Configuration;
namespace DeStream.Stratis.Bitcoin.Configuration
{
/// <summary>
/// Node configuration complied from both the application command line arguments and the configuration file.
/// </summary>
public class DeStreamNodeSettings : NodeSettings
{
/// <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 DeStreamNodeSettings(Network innerNetwork = null, ProtocolVersion protocolVersion = SupportedProtocolVersion,
string agent = "DeStream", string[] args = null, bool loadConfiguration = true)
: base (innerNetwork, protocolVersion, agent, args, loadConfiguration)
{
}
/// <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 override 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("DeStreamNode", 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");
// 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;
}
}
}
\ No newline at end of file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>DeStream FullNode</Description>
<AssemblyTitle>DeStream.Stratis.Bitcoin</AssemblyTitle>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>DeStream.Stratis.Bitcoin</AssemblyName>
<PackageId>DeStream.Stratis.Bitcoin</PackageId>
<GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
<GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
<GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
<Version>1.1.0-beta</Version>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Base\**" />
<Compile Remove="BlockPulling\**" />
<Compile Remove="Broadcasting\**" />
<Compile Remove="Builder\**" />
<EmbeddedResource Remove="Base\**" />
<EmbeddedResource Remove="BlockPulling\**" />
<EmbeddedResource Remove="Broadcasting\**" />
<EmbeddedResource Remove="Builder\**" />
<None Remove="Base\**" />
<None Remove="BlockPulling\**" />
<None Remove="Broadcasting\**" />
<None Remove="Builder\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="ConcurrentHashSet" Version="1.0.2" />
<PackageReference Include="DBreeze" Version="1.89.0" />
<PackageReference Include="NLog" Version="5.0.0-beta09" />
<PackageReference Include="NLog.Extensions.Logging" Version="1.0.0-rtm-beta5" />
<PackageReference Include="System.Reactive" Version="3.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Formatters.Json" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.0" />
<PackageReference Include="System.ValueTuple" Version="4.3.1" />
<PackageReference Include="System.Xml.XmlSerializer" Version="4.3.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Stratis.Bitcoin\Stratis.Bitcoin.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Configuration\" />
</ItemGroup>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputType>Library</OutputType>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<DefineConstants>$(DefineConstants);NETCORE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<NoWarn>1701;1702;1705;IDE0008;</NoWarn>
<DocumentationFile></DocumentationFile>
</PropertyGroup>
</Project>
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Stratis.Bitcoin")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Stratis.Bitcoin")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("a6c18cae-7246-41b1-bfd6-c54ba1694ac2")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.1.0.0")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: InternalsVisibleTo("Stratis.Bitcoin.Tests")]
...@@ -95,11 +95,6 @@ namespace Stratis.Bitcoin.Cli ...@@ -95,11 +95,6 @@ namespace Stratis.Bitcoin.Cli
defaultRestApiPort = 37221; defaultRestApiPort = 37221;
network = Network.StratisMain; network = Network.StratisMain;
} }
else if (networkName.Contains("destream"))
{
defaultRestApiPort = 37221;
network = Network.StratisMain;
}
else else
{ {
defaultRestApiPort = 37220; defaultRestApiPort = 37220;
......
...@@ -160,7 +160,7 @@ namespace Stratis.Bitcoin.Configuration ...@@ -160,7 +160,7 @@ namespace Stratis.Bitcoin.Configuration
/// <summary>Minimum relay transaction fee for network.</summary> /// <summary>Minimum relay transaction fee for network.</summary>
public FeeRate MinRelayTxFeeRate { get; set; } public FeeRate MinRelayTxFeeRate { get; set; }
public TextFileConfiguration ConfigReader { get; private set; } public TextFileConfiguration ConfigReader { get; protected set; }
/// <summary><c>true</c> to sync time with other peers and calculate adjusted time, <c>false</c> to use our system clock only.</summary> /// <summary><c>true</c> to sync time with other peers and calculate adjusted time, <c>false</c> to use our system clock only.</summary>
public bool SyncTimeEnabled { get; set; } public bool SyncTimeEnabled { get; set; }
...@@ -181,7 +181,7 @@ namespace Stratis.Bitcoin.Configuration ...@@ -181,7 +181,7 @@ namespace Stratis.Bitcoin.Configuration
/// </summary> /// </summary>
/// <returns>Initialized node configuration.</returns> /// <returns>Initialized node configuration.</returns>
/// <exception cref="ConfigurationException">Thrown in case of any problems with the configuration file or command line arguments.</exception> /// <exception cref="ConfigurationException">Thrown in case of any problems with the configuration file or command line arguments.</exception>
public NodeSettings LoadConfiguration() public virtual NodeSettings LoadConfiguration()
{ {
// Configuration already loaded? // Configuration already loaded?
if (this.ConfigReader != null) if (this.ConfigReader != null)
...@@ -301,7 +301,7 @@ namespace Stratis.Bitcoin.Configuration ...@@ -301,7 +301,7 @@ namespace Stratis.Bitcoin.Configuration
/// Creates a default configuration file if no configuration file is found. /// Creates a default configuration file if no configuration file is found.
/// </summary> /// </summary>
/// <returns>Path to the configuration file.</returns> /// <returns>Path to the configuration file.</returns>
private string CreateDefaultConfigurationFile() protected string CreateDefaultConfigurationFile()
{ {
string configFilePath = Path.Combine(this.DataDir, this.Network.DefaultConfigFilename); string configFilePath = Path.Combine(this.DataDir, this.Network.DefaultConfigFilename);
this.Logger.LogDebug("Configuration file set to '{0}'.", configFilePath); this.Logger.LogDebug("Configuration file set to '{0}'.", configFilePath);
...@@ -330,7 +330,7 @@ namespace Stratis.Bitcoin.Configuration ...@@ -330,7 +330,7 @@ namespace Stratis.Bitcoin.Configuration
/// <param name="appName">Name of the node, which will be reflected in the name of the data directory.</param> /// <param name="appName">Name of the node, which will be reflected in the name of the data directory.</param>
/// <param name="network">Specification of the network the node runs on - regtest/testnet/mainnet.</param> /// <param name="network">Specification of the network the node runs on - regtest/testnet/mainnet.</param>
/// <returns>The top-level data directory path.</returns> /// <returns>The top-level data directory path.</returns>
private string CreateDefaultDataDirectories(string appName, Network network) protected string CreateDefaultDataDirectories(string appName, Network network)
{ {
string directoryPath; string directoryPath;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment