Add NetworkTranslator
ADD
WalletWasabi.Tests/UnitTests/BitcoinCore/ConfigTranslatorTests.cs
+using NBitcoin;
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Text;
+using WalletWasabi.BitcoinCore.Configuration;
+using WalletWasabi.BitcoinCore.Configuration.Whitening;
+using Xunit;
+
+namespace WalletWasabi.Tests.UnitTests.BitcoinCore
+{
+ public class ConfigTranslatorTests
+ {
+ [Fact]
+ public void TryGetRpcUserTests()
+ {
+ var config = new CoreConfig();
+ var translatorMain = new CoreConfigTranslator(config, Network.Main);
+ var translatorTest = new CoreConfigTranslator(config, Network.TestNet);
+ var translatorReg = new CoreConfigTranslator(config, Network.RegTest);
+ Assert.Null(translatorMain.TryGetRpcUser());
+ Assert.Null(translatorTest.TryGetRpcUser());
+ Assert.Null(translatorReg.TryGetRpcUser());
+
+ config.AddOrUpdate("rpcuser");
+ Assert.Null(translatorMain.TryGetRpcUser());
+ Assert.Null(translatorTest.TryGetRpcUser());
+ Assert.Null(translatorReg.TryGetRpcUser());
+ config.AddOrUpdate("rpcuser=foo");
+ Assert.Equal("foo", translatorMain.TryGetRpcUser());
+ Assert.Null(translatorTest.TryGetRpcUser());
+ Assert.Null(translatorReg.TryGetRpcUser());
+ config.AddOrUpdate("rpcuser=boo");
+ Assert.Equal("boo", translatorMain.TryGetRpcUser());
+ Assert.Null(translatorTest.TryGetRpcUser());
+ Assert.Null(translatorReg.TryGetRpcUser());
+ config.AddOrUpdate("main.rpcuser=ooh");
+ Assert.Equal("ooh", translatorMain.TryGetRpcUser());
+ Assert.Null(translatorTest.TryGetRpcUser());
+ Assert.Null(translatorReg.TryGetRpcUser());
+ config.AddOrUpdate("rpcuser=boo");
+ Assert.Equal("boo", translatorMain.TryGetRpcUser());
+ Assert.Null(translatorTest.TryGetRpcUser());
+ Assert.Null(translatorReg.TryGetRpcUser());
+ config.AddOrUpdate("test.rpcuser=boo");
+ Assert.Equal("boo", translatorMain.TryGetRpcUser());
+ Assert.Equal("boo", translatorTest.TryGetRpcUser());
+ Assert.Null(translatorReg.TryGetRpcUser());
+ config.AddOrUpdate("regtest.rpcuser=boo");
+ Assert.Equal("boo", translatorMain.TryGetRpcUser());
+ Assert.Equal("boo", translatorTest.TryGetRpcUser());
+ Assert.Equal("boo", translatorReg.TryGetRpcUser());
+ }
+
+ [Fact]
+ public void TryGetRpcPortTests()
+ {
+ var config = new CoreConfig();
+ var translator = new CoreConfigTranslator(config, Network.Main);
+ Assert.Null(translator.TryGetRpcPort());
+
+ config.AddOrUpdate("rpcport");
+ Assert.Null(translator.TryGetRpcPort());
+
+ config.AddOrUpdate("main.rpcport=1");
+ Assert.Equal(1, translator.TryGetRpcPort());
+
+ config.AddOrUpdate("rpcport=2");
+ Assert.Equal(2, translator.TryGetRpcPort());
+
+ config.AddOrUpdate("main.rpcport=foo");
+ Assert.Null(translator.TryGetRpcPort());
+ }
+
+ [Fact]
+ public void TryGetWhiteBindTests()
+ {
+ var config = new CoreConfig();
+ var translator = new CoreConfigTranslator(config, Network.Main);
+ Assert.Null(translator.TryGetWhiteBind());
+
+ config.AddOrUpdate("whitebind");
+ Assert.Null(translator.TryGetWhiteBind());
+
+ config.AddOrUpdate("main.whitebind=127.0.0.1:18444");
+ WhiteBind whiteBind = translator.TryGetWhiteBind();
+ var ipEndPoint = whiteBind.EndPoint as IPEndPoint;
+ Assert.Equal(IPAddress.Loopback, ipEndPoint.Address);
+ Assert.Equal(18444, ipEndPoint.Port);
+ Assert.Equal(string.Empty, whiteBind.Permissions);
+
+ config.AddOrUpdate("whitebind=127.0.0.1:0");
+ whiteBind = translator.TryGetWhiteBind();
+ ipEndPoint = whiteBind.EndPoint as IPEndPoint;
+ Assert.Equal(IPAddress.Loopback, ipEndPoint.Address);
+ Assert.Equal(0, ipEndPoint.Port);
+ Assert.Equal(string.Empty, whiteBind.Permissions);
+
+ config.AddOrUpdate("whitebind=127.0.0.1");
+ whiteBind = translator.TryGetWhiteBind();
+ ipEndPoint = whiteBind.EndPoint as IPEndPoint;
+ Assert.Equal(IPAddress.Loopback, ipEndPoint.Address);
+ // Default port.
+ Assert.Equal(8333, ipEndPoint.Port);
+ Assert.Equal(string.Empty, whiteBind.Permissions);
+
+ config.AddOrUpdate("whitebind=foo@127.0.0.1");
+ whiteBind = translator.TryGetWhiteBind();
+ ipEndPoint = whiteBind.EndPoint as IPEndPoint;
+ Assert.Equal(IPAddress.Loopback, ipEndPoint.Address);
+ Assert.Equal(8333, ipEndPoint.Port);
+ Assert.Equal("foo", whiteBind.Permissions);
+
+ config.AddOrUpdate("whitebind=foo,boo@127.0.0.1");
+ whiteBind = translator.TryGetWhiteBind();
+ ipEndPoint = whiteBind.EndPoint as IPEndPoint;
+ Assert.Equal(IPAddress.Loopback, ipEndPoint.Address);
+ Assert.Equal(8333, ipEndPoint.Port);
+ Assert.Equal("foo,boo", whiteBind.Permissions);
+
+ config.AddOrUpdate("main.whitebind=@@@");
+ Assert.Null(translator.TryGetWhiteBind());
+ }
+ }
+}

MODIFY
WalletWasabi/BitcoinCore/Configuration/CoreConfig.cs
WalletWasabi/BitcoinCore/Configuration/CoreConfig.cs
+using NBitcoin;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -45,7 +46,11 @@ namespace WalletWasabi.BitcoinCore.Configuration
{
if (line.HasKeyValuePair)
{
- var foundLine = Lines.FirstOrDefault(x => x.Key == line.Key);
+ var foundLine = Lines.FirstOrDefault(x =>
+ x.Key == line.Key
+ || $"main.{x.Key}" == line.Key
+ || x.Key == $"main.{line.Key}");
+
if (foundLine is null)
{
Lines.Add(line);

ADD
WalletWasabi/BitcoinCore/Configuration/CoreConfigTranslator.cs
+using NBitcoin;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using WalletWasabi.BitcoinCore.Configuration.Whitening;
+using WalletWasabi.Helpers;
+
+namespace WalletWasabi.BitcoinCore.Configuration
+{
+ public class CoreConfigTranslator
+ {
+ public CoreConfig Config { get; }
+ public Network Network { get; }
+
+ public CoreConfigTranslator(CoreConfig config, Network network)
+ {
+ Config = Guard.NotNull(nameof(config), config);
+ Network = Guard.NotNull(nameof(network), network);
+ }
+
+ public string TryGetValue(string key)
+ {
+ var configDic = Config.ToDictionary();
+ string result = null;
+ foreach (var networkPrefixWithDot in NetworkTranslator.GetConfigPrefixesWithDots(Network))
+ {
+ var found = configDic.TryGet($"{networkPrefixWithDot}{key}");
+ if (found is { })
+ {
+ result = found;
+ }
+ }
+
+ return result;
+ }
+
+ public string TryGetRpcUser() => TryGetValue("rpcuser");
+
+ public string TryGetRpcPassword() => TryGetValue("rpcpassword");
+
+ public string TryGetRpcCookieFile() => TryGetValue("rpccookiefile");
+
+ public string TryGetRpcHost() => TryGetValue("rpchost");
+
+ public int? TryGetRpcPort()
+ {
+ var stringValue = TryGetValue("rpcport");
+ if (stringValue is { } && int.TryParse(stringValue, out int value))
+ {
+ return value;
+ }
+
+ return null;
+ }
+
+ public WhiteBind TryGetWhiteBind()
+ {
+ var stringValue = TryGetValue("whitebind");
+ if (stringValue is { } && WhiteBind.TryParse(stringValue, Network, out WhiteBind value))
+ {
+ return value;
+ }
+
+ return null;
+ }
+
+ public WhiteList TryGetWhiteList()
+ {
+ var stringValue = TryGetValue("whitelist");
+ if (stringValue is { } && WhiteList.TryParse(stringValue, Network, out WhiteList value))
+ {
+ return value;
+ }
+
+ return null;
+ }
+ }
+}

MODIFY
WalletWasabi/BitcoinCore/Configuration/NetworkTranslator.cs
WalletWasabi/BitcoinCore/Configuration/NetworkTranslator.cs
using NBitcoin;
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Text;
using WalletWasabi.Exceptions;
using WalletWasabi.Helpers;

ADD
WalletWasabi/BitcoinCore/Configuration/Whitening/WhiteBind.cs
+using NBitcoin;
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Text;
+
+namespace WalletWasabi.BitcoinCore.Configuration.Whitening
+{
+ public class WhiteBind : WhiteEntry
+ {
+ public static bool TryParse(string value, Network network, out WhiteBind white)
+ => TryParse<WhiteBind>(value, network, out white);
+ }
+}

ADD
WalletWasabi/BitcoinCore/Configuration/Whitening/WhiteEntry.cs
+using NBitcoin;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Text;
+using WalletWasabi.Helpers;
+
+namespace WalletWasabi.BitcoinCore.Configuration.Whitening
+{
+ public abstract class WhiteEntry
+ {
+ public string Permissions { get; private set; } = string.Empty;
+ public EndPoint EndPoint { get; private set; } = null;
+
+ public static bool TryParse<T>(string value, Network network, out T whiteEntry) where T : WhiteEntry, new()
+ {
+ whiteEntry = null;
+ // https://github.com/bitcoin/bitcoin/pull/16248
+ var parts = value?.Split('@');
+ if (parts is { })
+ {
+ if (EndPointParser.TryParse(parts.LastOrDefault(), network.DefaultPort, out EndPoint endPoint))
+ {
+ whiteEntry = new T();
+ whiteEntry.EndPoint = endPoint;
+ if (parts.Length > 1)
+ {
+ whiteEntry.Permissions = parts.First();
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+}

ADD
WalletWasabi/BitcoinCore/Configuration/Whitening/WhiteList.cs
+using NBitcoin;
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Text;
+
+namespace WalletWasabi.BitcoinCore.Configuration.Whitening
+{
+ public class WhiteList : WhiteEntry
+ {
+ public static bool TryParse(string value, Network network, out WhiteList white)
+ => TryParse<WhiteList>(value, network, out white);
+ }
+}

MODIFY
WalletWasabi/BitcoinCore/CoreNode.cs
WalletWasabi/BitcoinCore/CoreNode.cs
@@ -14,6 +14,7 @@ using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using WalletWasabi.BitcoinCore.Configuration;
+using WalletWasabi.BitcoinCore.Configuration.Whitening;
using WalletWasabi.BitcoinCore.Endpointing;
using WalletWasabi.BitcoinCore.Monitoring;
using WalletWasabi.BitcoinCore.Processes;
@@ -61,60 +62,14 @@ namespace WalletWasabi.BitcoinCore
}
cancel.ThrowIfCancellationRequested();
- var configDic = coreNode.Config.ToDictionary();
- string rpcUser = null;
- string rpcPassword = null;
- string whitebindPermissions = null;
- EndPoint whitebindEndPoint = null;
- string rpcHost = null;
- int? rpcPort = null;
- string rpcCookieFilePath = null;
- foreach (var networkPrefixWithDot in NetworkTranslator.GetConfigPrefixesWithDots(coreNode.Network))
- {
- var rpcc = configDic.TryGet($"{networkPrefixWithDot}rpccookiefile");
- var ru = configDic.TryGet($"{networkPrefixWithDot}rpcuser");
- var rp = configDic.TryGet($"{networkPrefixWithDot}rpcpassword");
- var wbs = configDic.TryGet($"{networkPrefixWithDot}whitebind");
- var rpst = configDic.TryGet($"{networkPrefixWithDot}rpchost");
- var rpts = configDic.TryGet($"{networkPrefixWithDot}rpcport");
-
- if (rpcc is { })
- {
- rpcCookieFilePath = rpcc;
- }
- if (ru is { })
- {
- rpcUser = ru;
- }
- if (rp is { })
- {
- rpcPassword = rp;
- }
-
- // https://github.com/bitcoin/bitcoin/pull/16248
- var wbsParts = wbs?.Split('@');
- if (wbsParts is { })
- {
- if (EndPointParser.TryParse(wbsParts.LastOrDefault(), coreNode.Network.DefaultPort, out EndPoint wbEndPoint))
- {
- whitebindEndPoint = wbEndPoint;
- }
-
- if (wbsParts.Length > 1)
- {
- whitebindPermissions = wbsParts.First();
- }
- }
+ var configTranslator = new CoreConfigTranslator(coreNode.Config, coreNode.Network);
- if (rpst is { })
- {
- rpcHost = rpst;
- }
- if (rpts is { } && int.TryParse(rpts, out int rpt))
- {
- rpcPort = rpt;
- }
- }
+ string rpcUser = configTranslator.TryGetRpcUser();
+ string rpcPassword = configTranslator.TryGetRpcPassword();
+ string rpcCookieFilePath = configTranslator.TryGetRpcCookieFile();
+ string rpcHost = configTranslator.TryGetRpcHost();
+ int? rpcPort = configTranslator.TryGetRpcPort();
+ WhiteBind whiteBind = configTranslator.TryGetWhiteBind();
string authString;
bool cookieAuth = rpcCookieFilePath is { };
@@ -129,7 +84,7 @@ namespace WalletWasabi.BitcoinCore
authString = $"{rpcUser}:{rpcPassword}";
}
- coreNode.P2pEndPoint = whitebindEndPoint ?? coreNodeParams.P2pEndPointStrategy.EndPoint;
+ coreNode.P2pEndPoint = whiteBind?.EndPoint ?? coreNodeParams.P2pEndPointStrategy.EndPoint;
rpcHost ??= coreNodeParams.RpcEndPointStrategy.EndPoint.GetHostOrDefault();
rpcPort ??= coreNodeParams.RpcEndPointStrategy.EndPoint.GetPortOrDefault();
EndPointParser.TryParse($"{rpcHost}:{rpcPort}", coreNode.Network.RPCPort, out EndPoint rpce);
@@ -152,7 +107,7 @@ namespace WalletWasabi.BitcoinCore
IoHelpers.EnsureDirectoryExists(coreNode.DataDir);
var configPrefix = NetworkTranslator.GetConfigPrefix(coreNode.Network);
- var whiteBindPermissionsPart = whitebindPermissions is { } ? $"{whitebindPermissions}@" : "";
+ var whiteBindPermissionsPart = !string.IsNullOrWhiteSpace(whiteBind?.Permissions) ? $"{whiteBind?.Permissions}@" : "";
var desiredConfigLines = new List<string>()
{
$"{configPrefix}.server = 1",

Add NetworkTranslator