Introduce EndPointParser
MODIFY
WalletWasabi.Backend/Config.cs
WalletWasabi.Backend/Config.cs
@@ -170,52 +170,53 @@ namespace WalletWasabi.Backend
private bool TryEnsureBackwardsCompatibility(string jsonString)
{
- // Before Wasabi 1.1.7
- EndPoint obsoleteStringToEndPoint(string endPointString, int port = 0)
- {
- if (IPAddress.TryParse(endPointString, out IPAddress ipAddress))
- {
- return new IPEndPoint(ipAddress, port);
- }
-
- return new DnsEndPoint(endPointString, port);
- };
-
var jsObject = JsonConvert.DeserializeObject<JObject>(jsonString);
bool saveIt = false;
if (jsObject.TryGetValue("MainNetBitcoinCoreHost", out JToken jMainNetBitcoinCoreHost))
{
int port = Constants.DefaultMainNetBintcoinP2pPort;
- if (jsObject.TryGetValue("MainNetBitcoinCorePort", out JToken jMainNetBitcoinCorePort))
+ if (jsObject.TryGetValue("MainNetBitcoinCorePort", out JToken jMainNetBitcoinCorePort) && int.TryParse(jMainNetBitcoinCorePort.ToString(), out int p))
{
- port = int.Parse(jMainNetBitcoinCorePort.ToString());
+ port = p;
}
- MainNetBitcoinP2pEndPoint = obsoleteStringToEndPoint(jMainNetBitcoinCoreHost.ToString(), port);
+
+ if (EndPointParser.TryParse(jMainNetBitcoinCoreHost.ToString(), port, out EndPoint ep))
+ {
+ MainNetBitcoinP2pEndPoint = ep;
saveIt = true;
}
+ }
if (jsObject.TryGetValue("TestNetBitcoinCoreHost", out JToken jTestNetBitcoinCoreHost))
{
int port = Constants.DefaultTestNetBintcoinP2pPort;
- if (jsObject.TryGetValue("TestNetBitcoinCorePort", out JToken jTestNetBitcoinCorePort))
+ if (jsObject.TryGetValue("TestNetBitcoinCorePort", out JToken jTestNetBitcoinCorePort) && int.TryParse(jTestNetBitcoinCorePort.ToString(), out int p))
{
- port = int.Parse(jTestNetBitcoinCorePort.ToString());
+ port = p;
}
- TestNetBitcoinP2pEndPoint = obsoleteStringToEndPoint(jTestNetBitcoinCoreHost.ToString(), port);
+
+ if (EndPointParser.TryParse(jTestNetBitcoinCoreHost.ToString(), port, out EndPoint ep))
+ {
+ TestNetBitcoinP2pEndPoint = ep;
saveIt = true;
}
+ }
if (jsObject.TryGetValue("RegTestBitcoinCoreHost", out JToken jRegTestBitcoinCoreHost))
{
int port = Constants.DefaultRegTestBintcoinP2pPort;
- if (jsObject.TryGetValue("RegTestBitcoinCorePort", out JToken jRegTestBitcoinCorePort))
+ if (jsObject.TryGetValue("RegTestBitcoinCorePort", out JToken jRegTestBitcoinCorePort) && int.TryParse(jRegTestBitcoinCorePort.ToString(), out int p))
{
- port = int.Parse(jRegTestBitcoinCorePort.ToString());
+ port = p;
}
- RegTestBitcoinP2pEndPoint = obsoleteStringToEndPoint(jRegTestBitcoinCoreHost.ToString(), port);
+
+ if (EndPointParser.TryParse(jRegTestBitcoinCoreHost.ToString(), port, out EndPoint ep))
+ {
+ RegTestBitcoinP2pEndPoint = ep;
saveIt = true;
}
+ }
return saveIt;
}

MODIFY
WalletWasabi.Gui/Config.cs
WalletWasabi.Gui/Config.cs
@@ -427,62 +427,68 @@ namespace WalletWasabi.Gui
private bool TryEnsureBackwardsCompatibility(string jsonString)
{
- // Before Wasabi 1.1.7
- EndPoint obsoleteStringToEndPoint(string endPointString, int port = 0)
- {
- if (IPAddress.TryParse(endPointString, out IPAddress ipAddress))
- {
- return new IPEndPoint(ipAddress, port);
- }
-
- return new DnsEndPoint(endPointString, port);
- };
-
var jsObject = JsonConvert.DeserializeObject<JObject>(jsonString);
bool saveIt = false;
+
if (jsObject.TryGetValue("TorHost", out JToken jTorHost))
{
int port = Constants.DefaultTorSocksPort;
- if (jsObject.TryGetValue("TorSocks5Port", out JToken jTorSocks5Port))
+ if (jsObject.TryGetValue("TorSocks5Port", out JToken jTorSocks5Port) && int.TryParse(jTorSocks5Port.ToString(), out int p))
{
- port = int.Parse(jTorSocks5Port.ToString());
+ port = p;
}
- TorSocks5EndPoint = obsoleteStringToEndPoint(jTorHost.ToString(), port);
+
+ if (EndPointParser.TryParse(jTorHost.ToString(), port, out EndPoint ep))
+ {
+ TorSocks5EndPoint = ep;
saveIt = true;
}
+ }
if (jsObject.TryGetValue("MainNetBitcoinCoreHost", out JToken jMainNetBitcoinCoreHost))
{
int port = Constants.DefaultMainNetBintcoinP2pPort;
- if (jsObject.TryGetValue("MainNetBitcoinCorePort", out JToken jMainNetBitcoinCorePort))
+ if (jsObject.TryGetValue("MainNetBitcoinCorePort", out JToken jMainNetBitcoinCorePort) && int.TryParse(jMainNetBitcoinCorePort.ToString(), out int p))
{
- port = int.Parse(jMainNetBitcoinCorePort.ToString());
+ port = p;
}
- MainNetBitcoinP2pEndPoint = obsoleteStringToEndPoint(jMainNetBitcoinCoreHost.ToString(), port);
+
+ if (EndPointParser.TryParse(jMainNetBitcoinCoreHost.ToString(), port, out EndPoint ep))
+ {
+ MainNetBitcoinP2pEndPoint = ep;
saveIt = true;
}
+ }
if (jsObject.TryGetValue("TestNetBitcoinCoreHost", out JToken jTestNetBitcoinCoreHost))
{
int port = Constants.DefaultTestNetBintcoinP2pPort;
- if (jsObject.TryGetValue("TestNetBitcoinCorePort", out JToken jTestNetBitcoinCorePort))
+ if (jsObject.TryGetValue("TestNetBitcoinCorePort", out JToken jTestNetBitcoinCorePort) && int.TryParse(jTestNetBitcoinCorePort.ToString(), out int p))
{
- port = int.Parse(jTestNetBitcoinCorePort.ToString());
+ port = p;
}
- TestNetBitcoinP2pEndPoint = obsoleteStringToEndPoint(jTestNetBitcoinCoreHost.ToString(), port);
+
+ if (EndPointParser.TryParse(jTestNetBitcoinCoreHost.ToString(), port, out EndPoint ep))
+ {
+ TestNetBitcoinP2pEndPoint = ep;
saveIt = true;
}
+ }
if (jsObject.TryGetValue("RegTestBitcoinCoreHost", out JToken jRegTestBitcoinCoreHost))
{
int port = Constants.DefaultRegTestBintcoinP2pPort;
- if (jsObject.TryGetValue("RegTestBitcoinCorePort", out JToken jRegTestBitcoinCorePort))
+ if (jsObject.TryGetValue("RegTestBitcoinCorePort", out JToken jRegTestBitcoinCorePort) && int.TryParse(jRegTestBitcoinCorePort.ToString(), out int p))
{
- port = int.Parse(jRegTestBitcoinCorePort.ToString());
+ port = p;
}
- RegTestBitcoinP2pEndPoint = obsoleteStringToEndPoint(jRegTestBitcoinCoreHost.ToString(), port);
+
+ if (EndPointParser.TryParse(jRegTestBitcoinCoreHost.ToString(), port, out EndPoint ep))
+ {
+ RegTestBitcoinP2pEndPoint = ep;
saveIt = true;
}
+ }
return saveIt;
}

MODIFY
WalletWasabi.Gui/Tabs/SettingsView.xaml
WalletWasabi.Gui/Tabs/SettingsView.xaml
<controls:GroupBox Title="{Binding Network, StringFormat=My Node for \{0\} }" TextBlock.FontSize="16" Padding="10" Margin="0 5 10 5">
<StackPanel Orientation="Vertical" Spacing="5">
<StackPanel Margin="0 10" Spacing="5">
- <TextBlock>Host</TextBlock>
- <TextBox Text="{Binding LocalNodeHost}" />
- </StackPanel>
- <Separator />
- <StackPanel Spacing="5">
- <TextBlock>Port</TextBlock>
- <TextBox Text="{Binding LocalNodePort}" />
+ <TextBlock>Bitcoin P2P Endpoint</TextBlock>
+ <TextBox Text="{Binding BitcoinP2pEndPoint}" />
</StackPanel>
</StackPanel>
</controls:GroupBox>
<TextBlock VerticalAlignment="Center">Tor can be turned off for debugging.</TextBlock>
</StackPanel>
<StackPanel Margin="0 10" Spacing="5">
- <TextBlock>Host</TextBlock>
- <TextBox Text="{Binding TorHost}" />
- </StackPanel>
- <StackPanel Spacing="5">
- <TextBlock>Port</TextBlock>
- <TextBox Text="{Binding TorPort}" />
+ <TextBlock>Tor SOCKS5 Endpoint</TextBlock>
+ <TextBox Text="{Binding TorSocks5EndPoint}" />
</StackPanel>
</StackPanel>
</controls:GroupBox>

MODIFY
WalletWasabi.Gui/Tabs/SettingsViewModel.cs
WalletWasabi.Gui/Tabs/SettingsViewModel.cs
@@ -21,9 +21,7 @@ namespace WalletWasabi.Gui.Tabs
private string _network;
private string _torHost;
- private string _torPort;
private string _localNodeHost;
- private string _localNodePort;
private bool _autocopy;
private bool _useTor;
private bool _isModified;
@@ -149,13 +147,6 @@ namespace WalletWasabi.Gui.Tabs
set => this.RaiseAndSetIfChanged(ref _torHost, value);
}
- [ValidateMethod(nameof(ValidateTorPort))]
- public string TorPort
- {
- get => _torPort;
- set => this.RaiseAndSetIfChanged(ref _torPort, value);
- }
-
[ValidateMethod(nameof(ValidateLocalNodeHost))]
public string LocalNodeHost
{
@@ -163,13 +154,6 @@ namespace WalletWasabi.Gui.Tabs
set => this.RaiseAndSetIfChanged(ref _localNodeHost, value);
}
- [ValidateMethod(nameof(ValidateLocalNodePort))]
- public string LocalNodePort
- {
- get => _localNodePort;
- set => this.RaiseAndSetIfChanged(ref _localNodePort, value);
- }
-
public bool IsModified
{
get => _isModified;
@@ -316,12 +300,6 @@ namespace WalletWasabi.Gui.Tabs
public string ValidateLocalNodeHost()
=> ValidateHost(LocalNodeHost);
- public string ValidateTorPort()
- => ValidatePort(TorPort);
-
- public string ValidateLocalNodePort()
- => ValidatePort(LocalNodePort);
-
public string ValidateSomePrivacyLevel()
=> ValidatePrivacyLevel(SomePrivacyLevel);
@@ -385,22 +363,6 @@ namespace WalletWasabi.Gui.Tabs
return "Invalid host.";
}
- public string ValidatePort(string port)
- {
- if (string.IsNullOrEmpty(port))
- {
- return string.Empty;
- }
-
- var thePort = port.Trim();
- if (ushort.TryParse(thePort, out var p) && p > 1024)
- {
- return string.Empty;
- }
-
- return "Invalid port.";
- }
-
private void OpenConfigFile()
{
IoHelpers.OpenFileInTextEditor(Global.Config.FilePath);

ADD
WalletWasabi/Helpers/EndPointParser.cs
+using System;
+using System.Collections.Generic;
+using System.Text;
+using WalletWasabi.Helpers;
+
+namespace System.Net
+{
+ public static class EndPointParser
+ {
+ public static string ToString(this EndPoint me, int defaultPort)
+ {
+ string host;
+ int port;
+ if (me is DnsEndPoint dnsEndPoint)
+ {
+ host = dnsEndPoint.Host;
+ port = dnsEndPoint.Port;
+ }
+ else if (me is IPEndPoint ipEndPoint)
+ {
+ host = ipEndPoint.Address.ToString();
+ port = ipEndPoint.Port;
+ }
+ else
+ {
+ throw new FormatException($"Invalid endpoint: {me.ToString()}");
+ }
+
+ if (port == 0)
+ {
+ port = defaultPort;
+ }
+
+ var endPointString = $"{host}:{port}";
+
+ return endPointString;
+ }
+
+ public static bool TryParse(string endPointString, int defaultPort, out EndPoint endPoint)
+ {
+ endPoint = null;
+
+ endPointString = Guard.Correct(endPointString);
+ endPointString = endPointString.TrimEnd('/');
+ endPointString = endPointString.TrimEnd(':');
+
+ var lastIndex = endPointString.LastIndexOf(':');
+
+ string portString = null;
+ if (lastIndex != -1)
+ {
+ portString = endPointString.Substring(endPointString.LastIndexOf(':') + 1);
+ }
+
+ if (portString is null || !int.TryParse(portString, out int port))
+ {
+ port = defaultPort;
+ }
+
+ string host = endPointString.TrimEnd(portString, StringComparison.OrdinalIgnoreCase).TrimEnd(':');
+
+ if (IPAddress.TryParse(host, out IPAddress addr))
+ {
+ endPoint = new IPEndPoint(addr, port);
+ }
+ else
+ {
+ try
+ {
+ endPoint = new DnsEndPoint(host, port);
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+}

MODIFY
WalletWasabi/JsonConverters/EndPointJsonConverter.cs
WalletWasabi/JsonConverters/EndPointJsonConverter.cs
@@ -34,66 +34,29 @@ namespace WalletWasabi.JsonConverters
/// <inheritdoc />
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
- string endPointString = Guard.Correct(reader.Value as string);
- endPointString = endPointString.TrimEnd('/');
- endPointString = endPointString.TrimEnd(':');
-
- var lastIndex = endPointString.LastIndexOf(':');
-
- string portString = null;
- if (lastIndex != -1)
- {
- portString = endPointString.Substring(endPointString.LastIndexOf(':') + 1);
- }
-
- if (portString is null || !int.TryParse(portString, out int port))
+ string endPointString = reader.Value as string;
+ if (EndPointParser.TryParse(endPointString, DefaultPort, out EndPoint endPoint))
{
- port = DefaultPort;
- }
-
- string host = endPointString.TrimEnd(portString, StringComparison.OrdinalIgnoreCase).TrimEnd(':');
-
- EndPoint endPoint;
- if (IPAddress.TryParse(host, out IPAddress addr))
- {
- endPoint = new IPEndPoint(addr, port);
+ return endPoint;
}
else
{
- endPoint = new DnsEndPoint(host, port);
+ throw new FormatException($"{nameof(endPointString)} is in the wrong format: {endPointString}.");
}
-
- return endPoint;
}
/// <inheritdoc />
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
- string host;
- int port;
- if (value is DnsEndPoint dnsEndPoint)
- {
- host = dnsEndPoint.Host;
- port = dnsEndPoint.Port;
- }
- else if (value is IPEndPoint ipEndPoint)
+ if (value is EndPoint endPoint)
{
- host = ipEndPoint.Address.ToString();
- port = ipEndPoint.Port;
+ var endPointString = endPoint.ToString(DefaultPort);
+ writer.WriteValue(endPointString);
}
else
{
- throw new FormatException($"Invalid endpoint: {value.ToString()}");
- }
-
- if (port == 0)
- {
- port = DefaultPort;
+ throw new NotSupportedException($"{nameof(EndPointJsonConverter)} can only convert {nameof(EndPoint)}.");
}
-
- var endPointString = $"{host}:{port}";
-
- writer.WriteValue(endPointString);
}
}
}

Introduce EndPointParser