Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove some mapping boilerplate #2023

Merged
merged 11 commits into from Jul 30, 2019
Next

Remove some mapping boilerplate

  • Loading branch information...
NicolasDorier committed Jul 26, 2019
commit d7fdaf060ce928ac30509e4644b096ece14ff208
@@ -2,6 +2,7 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.Text;
@@ -19,118 +20,134 @@ namespace WalletWasabi.Gui
[JsonObject(MemberSerialization.OptIn)]
public class Config : IConfig
{
public const int DefaultPrivacyLevelSome = 2;
public const int DefaultPrivacyLevelFine = 21;
public const int DefaultPrivacyLevelStrong = 50;
public const int DefaultMixUntilAnonymitySet = 50;
public const int DefaultTorSock5Port = 9050;
public static readonly Money DefaultDustThreshold = Money.Coins(0.0001m);
/// <inheritdoc />
public string FilePath { get; private set; }

[JsonProperty(PropertyName = "Network")]
[JsonConverter(typeof(NetworkJsonConverter))]
public Network Network { get; internal set; }
public Network Network { get; internal set; } = Network.Main;
This conversation was marked as resolved by molnard

This comment has been minimized.

Copy link
@molnard

molnard Jul 26, 2019

Collaborator

In Wasabi inline initializations are not used do it in the constructor instead. As this is a coding convention not dogma I am invoking @nopara73 to decide. Additionally there are some differences between the two procedure:
https://medium.com/datadriveninvestor/why-inline-initialization-is-not-just-syntax-sugar-in-c-3df25b5022fe

This comment has been minimized.

Copy link
@lontivero

lontivero Jul 26, 2019

Collaborator

IMO this is okay, we already have inline initializations everywhere and @nopara73 uses it.


[JsonProperty(PropertyName = "MainNetBackendUriV3")]
[DefaultValue("http://wasabiukrxmkdgve5kynjztuovbg43uxcbcxn6y2okcrsg7gb6jdmbad.onion/")]
[JsonProperty(PropertyName = "MainNetBackendUriV3", DefaultValueHandling = DefaultValueHandling.Populate)]
public string MainNetBackendUriV3 { get; private set; }

[JsonProperty(PropertyName = "TestNetBackendUriV3")]
[DefaultValue("http://testwnp3fugjln6vh5vpj7mvq3lkqqwjj3c2aafyu7laxz42kgwh2rad.onion/")]
[JsonProperty(PropertyName = "TestNetBackendUriV3", DefaultValueHandling = DefaultValueHandling.Populate)]
public string TestNetBackendUriV3 { get; private set; }

[JsonProperty(PropertyName = "MainNetFallbackBackendUri")]
[DefaultValue("https://wasabiwallet.io/")]
[JsonProperty(PropertyName = "MainNetFallbackBackendUri", DefaultValueHandling = DefaultValueHandling.Populate)]
public string MainNetFallbackBackendUri { get; private set; }

[JsonProperty(PropertyName = "TestNetFallbackBackendUri")]
[DefaultValue("https://wasabiwallet.co/")]
[JsonProperty(PropertyName = "TestNetFallbackBackendUri", DefaultValueHandling = DefaultValueHandling.Populate)]
public string TestNetFallbackBackendUri { get; private set; }

[JsonProperty(PropertyName = "RegTestBackendUriV3")]
[DefaultValue("http://localhost:37127/")]
[JsonProperty(PropertyName = "RegTestBackendUriV3", DefaultValueHandling = DefaultValueHandling.Populate)]
public string RegTestBackendUriV3 { get; private set; }

[JsonProperty(PropertyName = "UseTor")]
public bool? UseTor { get; internal set; }
[DefaultValue(true)]
[JsonProperty(PropertyName = "UseTor", DefaultValueHandling = DefaultValueHandling.Populate)]
public bool UseTor { get; internal set; }

[JsonProperty(PropertyName = "TorSocks5EndPoint")]
[JsonConverter(typeof(EndPointJsonConverter), Constants.DefaultTorSocksPort)]
public EndPoint TorSocks5EndPoint { get; internal set; }
public EndPoint TorSocks5EndPoint { get; internal set; } = new IPEndPoint(IPAddress.Loopback, Constants.DefaultTorSocksPort);

[JsonProperty(PropertyName = "MainNetBitcoinP2pEndPoint")]
[JsonConverter(typeof(EndPointJsonConverter), Constants.DefaultMainNetBitcoinP2pPort)]
public EndPoint MainNetBitcoinP2pEndPoint { get; internal set; }
public EndPoint MainNetBitcoinP2pEndPoint { get; internal set; } = new IPEndPoint(IPAddress.Loopback, Constants.DefaultMainNetBitcoinP2pPort);

[JsonProperty(PropertyName = "TestNetBitcoinP2pEndPoint")]
[JsonConverter(typeof(EndPointJsonConverter), Constants.DefaultTestNetBitcoinP2pPort)]
public EndPoint TestNetBitcoinP2pEndPoint { get; internal set; }
public EndPoint TestNetBitcoinP2pEndPoint { get; internal set; } = new IPEndPoint(IPAddress.Loopback, Constants.DefaultTestNetBitcoinP2pPort);

[JsonProperty(PropertyName = "RegTestBitcoinP2pEndPoint")]
[JsonConverter(typeof(EndPointJsonConverter), Constants.DefaultRegTestBitcoinP2pPort)]
public EndPoint RegTestBitcoinP2pEndPoint { get; internal set; }
public EndPoint RegTestBitcoinP2pEndPoint { get; internal set; } = new IPEndPoint(IPAddress.Loopback, Constants.DefaultRegTestBitcoinP2pPort);

[JsonProperty(PropertyName = "MixUntilAnonymitySet")]
public int? MixUntilAnonymitySet
[DefaultValue(DefaultMixUntilAnonymitySet)]
[JsonProperty(PropertyName = "MixUntilAnonymitySet", DefaultValueHandling = DefaultValueHandling.Populate)]
public int MixUntilAnonymitySet
This conversation was marked as resolved by molnard

This comment has been minimized.

Copy link
@molnard

molnard Jul 26, 2019

Collaborator

We could go with this to remove nullable. What was the original intent of this? What came to my mind is to let these values to be null and if ppl do not change it then operate with the default value. So if later we decide to change the default in the source code the clients with null values will pick up the new default.
But I think during the development this feature was lost and now if there is no value we do not let it be and set it t the current default then write it to the file.
So it is working like a not nullable variable.

This comment has been minimized.

Copy link
@NicolasDorier

NicolasDorier Jul 26, 2019

Author Collaborator

My thought was that nullable to detect whether the MixUntilAnonymitySet was set or not, and if not, set it a default value. (At least this is how it was used)
Without being nullable, the default value would be 0 and I think @nopara73 did not know about that [DefaultValue] was a thing.

All code using MixUntilAnonymitySet outside of Config is assuming that it is not null by calling .Value without any check.

I am not convinced there is value to keep the ability to change the default value for people not having set it between builds.

This comment has been minimized.

Copy link
@lontivero

lontivero Jul 26, 2019

Collaborator

I would love to see all the nullables removed from Wasabi, they are a cancer in the code.

{
get => _mixUntilAnonymitySet;
internal set
{
if (_mixUntilAnonymitySet != value)
{
_mixUntilAnonymitySet = value;
if (value.HasValue && ServiceConfiguration != default)
if (ServiceConfiguration != default)
{
ServiceConfiguration.MixUntilAnonymitySet = value.Value;
ServiceConfiguration.MixUntilAnonymitySet = value;
}
}
}
}

[JsonProperty(PropertyName = "PrivacyLevelSome")]
public int? PrivacyLevelSome
[DefaultValue(DefaultPrivacyLevelSome)]
[JsonProperty(PropertyName = "PrivacyLevelSome", DefaultValueHandling = DefaultValueHandling.Populate)]
public int PrivacyLevelSome
{
get => _privacyLevelSome;
internal set
{
if (_privacyLevelSome != value)
{
_privacyLevelSome = value;
if (value.HasValue && ServiceConfiguration != default)
if (ServiceConfiguration != default)
{
ServiceConfiguration.PrivacyLevelSome = value.Value;
ServiceConfiguration.PrivacyLevelSome = value;
}
}
}
}

[JsonProperty(PropertyName = "PrivacyLevelFine")]
public int? PrivacyLevelFine
[DefaultValue(DefaultPrivacyLevelFine)]
[JsonProperty(PropertyName = "PrivacyLevelFine", DefaultValueHandling = DefaultValueHandling.Populate)]
public int PrivacyLevelFine
{
get => _privacyLevelFine;
internal set
{
if (_privacyLevelFine != value)
{
_privacyLevelFine = value;
if (value.HasValue && ServiceConfiguration != default)
if (ServiceConfiguration != default)
{
ServiceConfiguration.PrivacyLevelFine = value.Value;
ServiceConfiguration.PrivacyLevelFine = value;
}
}
}
}

[JsonProperty(PropertyName = "PrivacyLevelStrong")]
public int? PrivacyLevelStrong
[DefaultValue(DefaultPrivacyLevelStrong)]
[JsonProperty(PropertyName = "PrivacyLevelStrong", DefaultValueHandling = DefaultValueHandling.Populate)]
public int PrivacyLevelStrong
{
get => _privacyLevelStrong;
internal set
{
if (_privacyLevelStrong != value)
{
_privacyLevelStrong = value;
if (value.HasValue && ServiceConfiguration != default)
if (ServiceConfiguration != default)
{
ServiceConfiguration.PrivacyLevelStrong = value.Value;
ServiceConfiguration.PrivacyLevelStrong = value;
}
}
}
}

[JsonProperty(PropertyName = "DustThreshold")]
[JsonConverter(typeof(MoneyBtcJsonConverter))]
public Money DustThreshold { get; internal set; }
public Money DustThreshold { get; internal set; } = DefaultDustThreshold;

private Uri _backendUri;
private Uri _fallbackBackendUri;
@@ -188,10 +205,10 @@ public Uri GetFallbackBackendUri()
return _fallbackBackendUri;
}

private int? _mixUntilAnonymitySet;
private int? _privacyLevelSome;
private int? _privacyLevelFine;
private int? _privacyLevelStrong;
private int _mixUntilAnonymitySet;
private int _privacyLevelSome;
private int _privacyLevelFine;
private int _privacyLevelStrong;

public EndPoint GetBitcoinP2pEndPoint()
{
@@ -239,27 +256,7 @@ public async Task ToFileAsync()
public async Task LoadOrCreateDefaultFileAsync()
{
AssertFilePathSet();

Network = Network.Main;

MainNetBackendUriV3 = "http://wasabiukrxmkdgve5kynjztuovbg43uxcbcxn6y2okcrsg7gb6jdmbad.onion/";
TestNetBackendUriV3 = "http://testwnp3fugjln6vh5vpj7mvq3lkqqwjj3c2aafyu7laxz42kgwh2rad.onion/";
MainNetFallbackBackendUri = "https://wasabiwallet.io/";
TestNetFallbackBackendUri = "https://wasabiwallet.co/";
RegTestBackendUriV3 = "http://localhost:37127/";

UseTor = true;
TorSocks5EndPoint = new IPEndPoint(IPAddress.Loopback, Constants.DefaultTorSocksPort);

MainNetBitcoinP2pEndPoint = new IPEndPoint(IPAddress.Loopback, Constants.DefaultMainNetBitcoinP2pPort);
TestNetBitcoinP2pEndPoint = new IPEndPoint(IPAddress.Loopback, Constants.DefaultTestNetBitcoinP2pPort);
RegTestBitcoinP2pEndPoint = new IPEndPoint(IPAddress.Loopback, Constants.DefaultRegTestBitcoinP2pPort);

MixUntilAnonymitySet = 50;
PrivacyLevelSome = 2;
PrivacyLevelFine = 21;
PrivacyLevelStrong = 50;
DustThreshold = Money.Coins(0.0001m);
JsonConvert.PopulateObject("{}", this);

if (!File.Exists(FilePath))
{
@@ -270,41 +267,53 @@ public async Task LoadOrCreateDefaultFileAsync()
await LoadFileAsync();
}

ServiceConfiguration = new ServiceConfiguration(MixUntilAnonymitySet.Value, PrivacyLevelSome.Value, PrivacyLevelFine.Value, PrivacyLevelStrong.Value, GetBitcoinP2pEndPoint(), DustThreshold);
ServiceConfiguration = new ServiceConfiguration(MixUntilAnonymitySet, PrivacyLevelSome, PrivacyLevelFine, PrivacyLevelStrong, GetBitcoinP2pEndPoint(), DustThreshold);

// Just debug convenience.
_backendUri = GetCurrentBackendUri();

await ToFileAsync();
}

public void SetP2PEndpoint(EndPoint endPoint)
{
switch (Network.Name)
{
case "Main":
MainNetBitcoinP2pEndPoint = endPoint;
break;
case "TestNet":
TestNetBitcoinP2pEndPoint = endPoint;
break;
case "RegTest":
RegTestBitcoinP2pEndPoint = endPoint;
break;
default:
throw new NotSupportedException("Unsupported network");
}
}

public EndPoint GetP2PEndpoint()
{
switch (Network.Name)
{
case "Main":
return MainNetBitcoinP2pEndPoint;
case "TestNet":
return TestNetBitcoinP2pEndPoint;
case "RegTest":
return RegTestBitcoinP2pEndPoint;
default:
throw new NotSupportedException("Unsupported network");
}
}

public async Task LoadFileAsync()
{
string jsonString = await File.ReadAllTextAsync(FilePath, Encoding.UTF8);

var config = JsonConvert.DeserializeObject<Config>(jsonString);

Network = config?.Network ?? Network;

MainNetBackendUriV3 = config?.MainNetBackendUriV3 ?? MainNetBackendUriV3;
TestNetBackendUriV3 = config?.TestNetBackendUriV3 ?? TestNetBackendUriV3;
MainNetFallbackBackendUri = config?.MainNetFallbackBackendUri ?? MainNetFallbackBackendUri;
TestNetFallbackBackendUri = config?.TestNetFallbackBackendUri ?? TestNetFallbackBackendUri;
RegTestBackendUriV3 = config?.RegTestBackendUriV3 ?? RegTestBackendUriV3;

UseTor = config?.UseTor ?? UseTor;
TorSocks5EndPoint = config?.TorSocks5EndPoint ?? TorSocks5EndPoint;

MainNetBitcoinP2pEndPoint = config?.MainNetBitcoinP2pEndPoint ?? MainNetBitcoinP2pEndPoint;
TestNetBitcoinP2pEndPoint = config?.TestNetBitcoinP2pEndPoint ?? TestNetBitcoinP2pEndPoint;
RegTestBitcoinP2pEndPoint = config?.RegTestBitcoinP2pEndPoint ?? RegTestBitcoinP2pEndPoint;

MixUntilAnonymitySet = config?.MixUntilAnonymitySet ?? MixUntilAnonymitySet;
PrivacyLevelSome = config?.PrivacyLevelSome ?? PrivacyLevelSome;
PrivacyLevelFine = config?.PrivacyLevelFine ?? PrivacyLevelFine;
PrivacyLevelStrong = config?.PrivacyLevelStrong ?? PrivacyLevelStrong;

DustThreshold = config?.DustThreshold ?? DustThreshold;
JsonConvert.PopulateObject(jsonString, this);

ServiceConfiguration = config?.ServiceConfiguration ?? ServiceConfiguration;

@@ -317,6 +326,12 @@ public async Task LoadFileAsync()
}
}

public void CopyFrom(Config config)
{
var configSerialized = JsonConvert.SerializeObject(config);
JsonConvert.PopulateObject(configSerialized, this);
}

/// <inheritdoc />
public async Task<bool> CheckFileChangeAsync()
{
@@ -328,10 +343,16 @@ public async Task<bool> CheckFileChangeAsync()
}

string jsonString = await File.ReadAllTextAsync(FilePath, Encoding.UTF8);
var newConfig = JsonConvert.DeserializeObject<JObject>(jsonString);
var currentConfig = JObject.FromObject(this);
var newConfig = JsonConvert.DeserializeObject<Config>(jsonString);

return !JToken.DeepEquals(newConfig, currentConfig);
return !AreDeepEqual(newConfig);
}

public bool AreDeepEqual(Config otherConfig)
{
var currentConfig = JObject.FromObject(this);
var otherConfigJson = JObject.FromObject(otherConfig);
return JToken.DeepEquals(otherConfigJson, currentConfig);
}

/// <inheritdoc />
@@ -397,13 +418,13 @@ public int GetTargetLevel(TargetPrivacy target)
return 0;

case TargetPrivacy.Some:
return PrivacyLevelSome.Value;
return PrivacyLevelSome;

case TargetPrivacy.Fine:
return PrivacyLevelFine.Value;
return PrivacyLevelFine;

case TargetPrivacy.Strong:
return PrivacyLevelStrong.Value;
return PrivacyLevelStrong;
}
return 0;
}
@@ -153,7 +153,7 @@ public async Task InitializeNoWalletAsync()
var blocksFolderPath = Path.Combine(DataDir, $"Blocks{Network}");
var connectionParameters = new NodeConnectionParameters { UserAgent = "/Satoshi:0.18.0/" };

if (Config.UseTor.Value)
if (Config.UseTor)
{
Synchronizer = new WasabiSynchronizer(Network, BitcoinStore, () => Config.GetCurrentBackendUri(), Config.TorSocks5EndPoint);
}
@@ -187,7 +187,7 @@ public async Task InitializeNoWalletAsync()

#region TorProcessInitialization

if (Config.UseTor.Value)
if (Config.UseTor)
{
TorManager = new TorProcessManager(Config.TorSocks5EndPoint, TorLogsFile);
}
@@ -408,7 +408,7 @@ public async Task InitializeWalletServiceAsync(KeyManager keyManager)
await Task.Delay(100, token);
}

if (Config.UseTor.Value)
if (Config.UseTor)
{
ChaumianClient = new CcjClient(Synchronizer, Network, keyManager, () => Config.GetCurrentBackendUri(), Config.TorSocks5EndPoint);
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.