Connect to local (or LAN) bitcoin node
MODIFY
WalletWasabi.Gui/Config.cs
WalletWasabi.Gui/Config.cs
@@ -47,23 +47,11 @@ namespace WalletWasabi.Gui
[JsonProperty(PropertyName = "TorSocks5Port")]
public int? TorSocks5Port { get; internal set; }
- [JsonProperty(PropertyName = "BitcoinCoreDataDir")]
- public string BitcoinCoreDataDir
- {
- get => _bitcoinCoreDataDir;
- internal set
- {
- if (_bitcoinCoreDataDir != value)
- {
- _bitcoinCoreDataDir = value;
+ [JsonProperty(PropertyName = "BitcoinCoreHost")]
+ public string BitcoinCoreHost { get; internal set; }
- if (!string.IsNullOrWhiteSpace(value) && ServiceConfiguration != default)
- {
- ServiceConfiguration.BitcoinCoreDataDir = value;
- }
- }
- }
- }
+ [JsonProperty(PropertyName = "BitcoinCorePort")]
+ public int? BitcoinCorePort { get; internal set; }
[JsonProperty(PropertyName = "MixUntilAnonymitySet")]
public int? MixUntilAnonymitySet
@@ -188,7 +176,7 @@ namespace WalletWasabi.Gui
private int? _privacyLevelSome;
private int? _privacyLevelFine;
private int? _privacyLevelStrong;
- private string _bitcoinCoreDataDir;
+ private IPEndPoint _bitcoinCoreEndPoint;
public IPEndPoint GetTorSocks5EndPoint()
{
@@ -201,6 +189,17 @@ namespace WalletWasabi.Gui
return _torSocks5EndPoint;
}
+ public IPEndPoint GetBitcoinCoreEndPoint()
+ {
+ if (_bitcoinCoreEndPoint is null)
+ {
+ var host = IPAddress.Parse(BitcoinCoreHost);
+ _bitcoinCoreEndPoint = new IPEndPoint(host, BitcoinCorePort ?? Network.DefaultPort);
+ }
+
+ return _bitcoinCoreEndPoint;
+ }
+
public Config()
{
_backendUri = null;
@@ -219,7 +218,8 @@ namespace WalletWasabi.Gui
string mainNetFallbackBackendUri,
string testNetFallbackBackendUri,
string regTestBackendUriV3,
- string bitcoinCoreDataDir,
+ string bitcoinCoreHost,
+ int? bitcoinCorePort,
string torHost,
int? torSocks5Port,
int? mixUntilAnonymitySet,
@@ -239,14 +239,15 @@ namespace WalletWasabi.Gui
TorHost = Guard.NotNullOrEmptyOrWhitespace(nameof(torHost), torHost);
TorSocks5Port = Guard.NotNull(nameof(torSocks5Port), torSocks5Port);
- BitcoinCoreDataDir = Guard.NotNullOrEmptyOrWhitespace(nameof(bitcoinCoreDataDir), bitcoinCoreDataDir);
+ BitcoinCoreHost = Guard.NotNullOrEmptyOrWhitespace(nameof(bitcoinCoreHost), bitcoinCoreHost);
+ BitcoinCorePort = Guard.NotNull(nameof(bitcoinCorePort), bitcoinCorePort);
MixUntilAnonymitySet = Guard.NotNull(nameof(mixUntilAnonymitySet), mixUntilAnonymitySet);
PrivacyLevelSome = Guard.NotNull(nameof(privacyLevelSome), privacyLevelSome);
PrivacyLevelFine = Guard.NotNull(nameof(privacyLevelFine), privacyLevelFine);
PrivacyLevelStrong = Guard.NotNull(nameof(privacyLevelStrong), privacyLevelStrong);
- ServiceConfiguration = new ServiceConfiguration(MixUntilAnonymitySet.Value, PrivacyLevelSome.Value, PrivacyLevelFine.Value, PrivacyLevelStrong.Value, BitcoinCoreDataDir);
+ ServiceConfiguration = new ServiceConfiguration(MixUntilAnonymitySet.Value, PrivacyLevelSome.Value, PrivacyLevelFine.Value, PrivacyLevelStrong.Value, GetBitcoinCoreEndPoint());
}
/// <inheritdoc />
@@ -272,7 +273,8 @@ namespace WalletWasabi.Gui
MainNetFallbackBackendUri = "https://wasabiwallet.io/";
TestNetFallbackBackendUri = "https://wasabiwallet.co/";
RegTestBackendUriV3 = "http://localhost:37127/";
- BitcoinCoreDataDir = EnvironmentHelpers.TryGetDefaultBitcoinCoreDataDir() ?? "/bitcoin"; // whatever
+ BitcoinCoreHost = IPAddress.Loopback.ToString();
+ BitcoinCorePort = Network.DefaultPort;
TorHost = IPAddress.Loopback.ToString();
TorSocks5Port = 9050;
@@ -282,8 +284,6 @@ namespace WalletWasabi.Gui
PrivacyLevelFine = 21;
PrivacyLevelStrong = 50;
- ServiceConfiguration = new ServiceConfiguration(MixUntilAnonymitySet.Value, PrivacyLevelSome.Value, PrivacyLevelFine.Value, PrivacyLevelStrong.Value, BitcoinCoreDataDir);
-
if (!File.Exists(FilePath))
{
Logger.LogInfo<Config>($"{nameof(Config)} file did not exist. Created at path: `{FilePath}`.");
@@ -293,6 +293,8 @@ namespace WalletWasabi.Gui
await LoadFileAsync();
}
+ ServiceConfiguration = new ServiceConfiguration(MixUntilAnonymitySet.Value, PrivacyLevelSome.Value, PrivacyLevelFine.Value, PrivacyLevelStrong.Value, GetBitcoinCoreEndPoint());
+
// Just debug convenience.
_backendUri = GetCurrentBackendUri();
@@ -311,7 +313,8 @@ namespace WalletWasabi.Gui
MainNetFallbackBackendUri = config.MainNetFallbackBackendUri ?? MainNetFallbackBackendUri;
TestNetFallbackBackendUri = config.TestNetFallbackBackendUri ?? TestNetFallbackBackendUri;
RegTestBackendUriV3 = config.RegTestBackendUriV3 ?? RegTestBackendUriV3;
- BitcoinCoreDataDir = config.BitcoinCoreDataDir ?? BitcoinCoreDataDir;
+ BitcoinCoreHost = config.BitcoinCoreHost ?? BitcoinCoreHost;
+ BitcoinCorePort = config.BitcoinCorePort ?? BitcoinCorePort;
TorHost = config.TorHost ?? TorHost;
TorSocks5Port = config.TorSocks5Port ?? TorSocks5Port;
@@ -375,7 +378,11 @@ namespace WalletWasabi.Gui
return true;
}
- if (BitcoinCoreDataDir != config.BitcoinCoreDataDir) // case sensitive
+ if (!BitcoinCoreHost.Equals(config.BitcoinCoreHost, StringComparison.OrdinalIgnoreCase)) // case sensitive
+ {
+ return true;
+ }
+ if (BitcoinCorePort != config.BitcoinCorePort)
{
return true;
}

MODIFY
WalletWasabi.Tests/P2pTests.cs
WalletWasabi.Tests/P2pTests.cs
@@ -6,6 +6,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Net;
using System.Threading;
using System.Threading.Tasks;
using WalletWasabi.Backend.Models;
@@ -92,7 +93,7 @@ namespace WalletWasabi.Tests
memPoolService,
nodes,
SharedFixture.DataDir,
- new ServiceConfiguration(50, 2, 21, 50, EnvironmentHelpers.TryGetDefaultBitcoinCoreDataDir()));
+ new ServiceConfiguration(50, 2, 21, 50, new IPEndPoint(IPAddress.Parse("127.0.0.1"), network.DefaultPort)));
Assert.True(Directory.Exists(blocksFolderPath));
try

MODIFY
WalletWasabi.Tests/RegTests.cs
WalletWasabi.Tests/RegTests.cs
@@ -81,7 +81,7 @@ namespace WalletWasabi.Tests
}
Global.Coordinator.UtxoReferee.Clear();
- var serviceConfiguration = new ServiceConfiguration(2, 2, 21, 50, EnvironmentHelpers.TryGetDefaultBitcoinCoreDataDir());
+ var serviceConfiguration = new ServiceConfiguration(2, 2, 21, 50, new IPEndPoint(IPAddress.Parse("127.0.0.1"), Global.RpcClient.Network.DefaultPort));
return ("password", Global.RpcClient, Global.RpcClient.Network, Global.Coordinator, serviceConfiguration);
}

MODIFY
WalletWasabi/Helpers/EnvironmentHelpers.cs
WalletWasabi/Helpers/EnvironmentHelpers.cs
@@ -70,55 +70,6 @@ namespace WalletWasabi.Helpers
return directory;
}
- public static string TryGetDefaultBitcoinCoreDataDir()
- {
- string directory = null;
-
- // https://en.bitcoin.it/wiki/Data_directory
- try
- {
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- {
- var localAppData = Environment.GetEnvironmentVariable("APPDATA");
- if (!string.IsNullOrEmpty(localAppData))
- {
- directory = Path.Combine(localAppData, "Bitcoin");
- }
- else
- {
- throw new DirectoryNotFoundException("Could not find suitable default Bitcoin Core datadir.");
- }
- }
- else
- {
- var home = Environment.GetEnvironmentVariable("HOME");
- if (!string.IsNullOrEmpty(home))
- {
- if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
- {
- directory = Path.Combine(home, "Library", "Application Support", "Bitcoin");
- }
- else // Linux
- {
- directory = Path.Combine(home, ".bitcoin");
- }
- }
- else
- {
- throw new DirectoryNotFoundException("Could not find suitable default Bitcoin Core datadir.");
- }
- }
-
- return directory;
- }
- catch (Exception ex)
- {
- Logger.LogDebug(ex, nameof(EnvironmentHelpers));
- }
-
- return directory;
- }
-
/// <summary>
/// Executes a command with bash.
/// https://stackoverflow.com/a/47918132/2061103

MODIFY
WalletWasabi/Services/WalletService.cs
WalletWasabi/Services/WalletService.cs
@@ -641,21 +641,43 @@ namespace WalletWasabi.Services
if (LocalBitcoinCoreNode == null || !LocalBitcoinCoreNode.IsConnected)
{
DisconnectDisposeNullLocalBitcoinCoreNode();
- LocalBitcoinCoreNode = Node.ConnectToLocal(Network);
- if(LocalBitcoinCoreNode.IsConnected)
+ using(var handshakeTimeout = CancellationTokenSource.CreateLinkedTokenSource(cancel))
{
+ handshakeTimeout.CancelAfter(TimeSpan.FromSeconds(10));
+ var nodeConnectionParameters = new NodeConnectionParameters()
+ {
+ ConnectCancellation = handshakeTimeout.Token,
+ IsRelay = false
+ };
+
+ //var localIpEndPoint = Utils.ParseIpEndpoint("localhost", Network.DefaultPort);
+ var localIpEndPoint = ServiceConfiguration.BitcoinCoreEndPoint;
+ var localNode = Node.Connect(Network, localIpEndPoint, nodeConnectionParameters);
try
{
- LocalBitcoinCoreNode.VersionHandshake(Constants.LocalNodeRequirements);
+ Logger.LogInfo<WalletService>($"TCP Connection succeed, handshaking...");
+ localNode.VersionHandshake(Constants.LocalNodeRequirements, handshakeTimeout.Token);
+ var peerServices = localNode.PeerVersion.Services;
+ /*
+ if(!peerServices.HasFlag(NodeServices.Network) && !peerServices.HasFlag(NodeServices.NODE_NETWORK_LIMITED))
+ {
+ throw new InvalidOperationException($"Wasabi cannot use the local node because it doesn't provide blocks.");
}
- catch(Exception)
+ */
+ Logger.LogInfo<WalletService>($"Handshake completed successfully");
+
+ if(!localNode.IsConnected)
{
- Logger.LogTrace<WalletService>("It connected to local node but it couldn't finish the version handshake. Local node could not meet the needed requirements.");
- throw;
+ throw new InvalidOperationException($"Wasabi could not complete the handshake with the local node and dropped the connection.{Environment.NewLine}" +
+ $"Probably this is because the node doesn't support retrieving full blocks or segwit serialization.)");
}
- if(LocalBitcoinCoreNode.State != NodeState.HandShaked)
+ LocalBitcoinCoreNode = localNode;
+ }
+ catch (OperationCanceledException) when (handshakeTimeout.IsCancellationRequested)
{
- throw new InvalidOperationException($"Local node is not in handshaked state. Ignoring local node.");
+ Logger.LogWarning<WalletService>($"Wasabi could not complete the handshake with the local node. Probably Wasabi is not whitelisted by the node.{Environment.NewLine}" +
+ $"Use \"whitebind\" or \"whitelist\" in the node configuration. (typically whitelist=127.0.0.1 if Wasabi and the node are on the same machine.)");
+ throw;
}
}
}

Connect to local (or LAN) bitcoin node