Add clearnet debugging feature. Closes
MODIFY
WalletWasabi.Gui/Config.cs
WalletWasabi.Gui/Config.cs
@@ -41,6 +41,9 @@ namespace WalletWasabi.Gui
[JsonProperty(PropertyName = "RegTestBackendUriV3")]
public string RegTestBackendUriV3 { get; private set; }
+ [JsonProperty(PropertyName = "UseTor")]
+ public bool? UseTor { get; internal set; }
+
[JsonProperty(PropertyName = "TorHost")]
public string TorHost { get; internal set; }
@@ -247,6 +250,7 @@ namespace WalletWasabi.Gui
string mainNetFallbackBackendUri,
string testNetFallbackBackendUri,
string regTestBackendUriV3,
+ bool? useTor,
string torHost,
int? torSocks5Port,
string mainNetBitcoinCoreHost,
@@ -269,6 +273,7 @@ namespace WalletWasabi.Gui
TestNetBackendUriV3 = Guard.NotNullOrEmptyOrWhitespace(nameof(testNetBackendUriV3), testNetBackendUriV3);
RegTestBackendUriV3 = Guard.NotNullOrEmptyOrWhitespace(nameof(regTestBackendUriV3), regTestBackendUriV3);
+ UseTor = Guard.NotNull(nameof(useTor), useTor);
TorHost = Guard.NotNullOrEmptyOrWhitespace(nameof(torHost), torHost);
TorSocks5Port = Guard.NotNull(nameof(torSocks5Port), torSocks5Port);
@@ -311,6 +316,7 @@ namespace WalletWasabi.Gui
TestNetFallbackBackendUri = "https://wasabiwallet.co/";
RegTestBackendUriV3 = "http://localhost:37127/";
+ UseTor = true;
TorHost = IPAddress.Loopback.ToString();
TorSocks5Port = 9050;
@@ -356,6 +362,7 @@ namespace WalletWasabi.Gui
TestNetFallbackBackendUri = config.TestNetFallbackBackendUri ?? TestNetFallbackBackendUri;
RegTestBackendUriV3 = config.RegTestBackendUriV3 ?? RegTestBackendUriV3;
+ UseTor = config.UseTor ?? UseTor;
TorHost = config.TorHost ?? TorHost;
TorSocks5Port = config.TorSocks5Port ?? TorSocks5Port;
@@ -416,6 +423,11 @@ namespace WalletWasabi.Gui
return true;
}
+ if (UseTor != config.UseTor)
+ {
+ return true;
+ }
+
if (!TorHost.Equals(config.TorHost, StringComparison.Ordinal))
{
return true;

MODIFY
WalletWasabi.Gui/Global.cs
WalletWasabi.Gui/Global.cs
@@ -169,7 +169,14 @@ namespace WalletWasabi.Gui
AddressManager = null;
TorManager = null;
+ if (Config.UseTor.Value)
+ {
TorManager = new TorProcessManager(Config.GetTorSocks5EndPoint(), TorLogsFile);
+ }
+ else
+ {
+ TorManager = TorProcessManager.Mock();
+ }
TorManager.Start(false, DataDir);
var fallbackRequestTestUri = new Uri(Config.GetFallbackBackendUri(), "/api/software/versions");
TorManager.StartMonitor(TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(7), DataDir, fallbackRequestTestUri);
@@ -263,7 +270,14 @@ namespace WalletWasabi.Gui
RegTestMemPoolServingNode = null;
}
+ if (Config.UseTor.Value)
+ {
Synchronizer = new WasabiSynchronizer(Network, IndexFilePath, () => Config.GetCurrentBackendUri(), Config.GetTorSocks5EndPoint());
+ }
+ else
+ {
+ Synchronizer = new WasabiSynchronizer(Network, IndexFilePath, Config.GetFallbackBackendUri(), null);
+ }
UpdateChecker = new UpdateChecker(Synchronizer.WasabiClient);
@@ -291,8 +305,15 @@ namespace WalletWasabi.Gui
private static CancellationTokenSource CancelWalletServiceInitialization = null;
public static async Task InitializeWalletServiceAsync(KeyManager keyManager)
+ {
+ if (Config.UseTor.Value)
{
ChaumianClient = new CcjClient(Synchronizer, Network, keyManager, () => Config.GetCurrentBackendUri(), Config.GetTorSocks5EndPoint());
+ }
+ else
+ {
+ ChaumianClient = new CcjClient(Synchronizer, Network, keyManager, Config.GetFallbackBackendUri(), null);
+ }
WalletService = new WalletService(keyManager, Synchronizer, ChaumianClient, MemPoolService, Nodes, DataDir, Config.ServiceConfiguration);
ChaumianClient.Start();

MODIFY
WalletWasabi.Gui/Tabs/SettingsView.xaml
WalletWasabi.Gui/Tabs/SettingsView.xaml
<controls:GroupBox Title="Tor" TextBlock.FontSize="16" Padding="10" Margin="0 5 10 5">
<StackPanel Orientation="Vertical">
+ <StackPanel Margin="0 10" Orientation="Horizontal">
+ <ToggleButton IsChecked="{Binding UseTor}" Content="{Binding UseTorText}" Margin="0 0 10 0" />
+ <TextBlock VerticalAlignment="Center">Tor can be turned off for debugging.</TextBlock>
+ </StackPanel>
<StackPanel Margin="0 10">
<TextBlock>Host</TextBlock>
<TextBox Text="{Binding TorHost}" />

MODIFY
WalletWasabi.Gui/Tabs/SettingsViewModel.cs
WalletWasabi.Gui/Tabs/SettingsViewModel.cs
@@ -19,6 +19,8 @@ namespace WalletWasabi.Gui.Tabs
private string _torPort;
private bool _autocopy;
private string _autocopyText;
+ private bool _useTor;
+ private string _useTorText;
private bool _isModified;
@@ -27,7 +29,7 @@ namespace WalletWasabi.Gui.Tabs
var config = new Config(Global.Config.FilePath);
Autocopy = (bool)Global.UiConfig.Autocopy;
- this.WhenAnyValue(x => x.Network, x => x.TorHost, x => x.TorPort).Subscribe(x => Save());
+ this.WhenAnyValue(x => x.Network, x => x.TorHost, x => x.TorPort, x => x.UseTor).Subscribe(x => Save());
this.WhenAnyValue(x => x.Autocopy).Subscribe(x =>
{
@@ -40,6 +42,11 @@ namespace WalletWasabi.Gui.Tabs
});
});
+ this.WhenAnyValue(x => x.UseTor).Subscribe(x =>
+ {
+ UseTorText = x ? "On" : "Off";
+ });
+
Dispatcher.UIThread.PostLogException(async () =>
{
await config.LoadFileAsync();
@@ -47,6 +54,7 @@ namespace WalletWasabi.Gui.Tabs
Network = config.Network.ToString();
TorHost = config.TorHost;
TorPort = config.TorSocks5Port.ToString();
+ UseTor = config.UseTor.Value;
IsModified = await Global.Config.CheckFileChangeAsync();
});
@@ -104,6 +112,18 @@ namespace WalletWasabi.Gui.Tabs
set => this.RaiseAndSetIfChanged(ref _autocopyText, value);
}
+ public bool UseTor
+ {
+ get => _useTor;
+ set => this.RaiseAndSetIfChanged(ref _useTor, value);
+ }
+
+ public string UseTorText
+ {
+ get => _useTorText;
+ set => this.RaiseAndSetIfChanged(ref _useTorText, value);
+ }
+
private void Save()
{
var isValid = string.IsNullOrEmpty(ValidateTorHost()) &&
@@ -120,12 +140,14 @@ namespace WalletWasabi.Gui.Tabs
var network = NBitcoin.Network.GetNetwork(Network);
var torHost = TorHost;
var torSocks5Port = int.TryParse(TorPort, out var port) ? (int?)port : null;
+ var useTor = UseTor;
- if (config.Network != network || config.TorHost != torHost || config.TorSocks5Port != torSocks5Port)
+ if (config.Network != network || config.TorHost != torHost || config.TorSocks5Port != torSocks5Port || config.UseTor != useTor)
{
config.Network = network;
config.TorHost = torHost;
config.TorSocks5Port = torSocks5Port;
+ config.UseTor = useTor;
await config.ToFileAsync();

MODIFY
WalletWasabi.Tests/TorTests.cs
WalletWasabi.Tests/TorTests.cs
@@ -44,6 +44,17 @@ namespace WalletWasabi.Tests
}
}
+ [Fact]
+ public async Task CanRequestClearnetAsync()
+ {
+ using (var client = new TorHttpClient(new Uri("https://jigsaw.w3.org/"), null))
+ {
+ var response = await client.SendAsync(HttpMethod.Get, "/HTTP/ChunkedScript");
+ var content = await response.Content.ReadAsStringAsync();
+ Assert.Equal(1000, Regex.Matches(content, "01234567890123456789012345678901234567890123456789012345678901234567890").Count);
+ }
+ }
+
[Fact]
public async Task CanDoBasicPostHttpsRequestAsync()
{
@@ -118,35 +129,33 @@ namespace WalletWasabi.Tests
}
}
- // Unavailable at the time of writing. Not sure if it's even needed.
- //[Fact]
- //public async Task CanRequestOnionV2Async()
- //{
- // using (var client = new TorHttpClient(new Uri("http://expyuzz4wqqyqhjn.onion/"), SharedFixture.TorSocks5Endpoint))
- // {
- // HttpResponseMessage response = await client.SendAsync(HttpMethod.Get, "");
- // var content = await response.Content.ReadAsStringAsync();
+ [Fact]
+ public async Task CanRequestOnionV2Async()
+ {
+ using (var client = new TorHttpClient(new Uri("http://expyuzz4wqqyqhjn.onion/"), SharedFixture.TorSocks5Endpoint))
+ {
+ HttpResponseMessage response = await client.SendAsync(HttpMethod.Get, "");
+ var content = await response.Content.ReadAsStringAsync();
- // Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
- // Assert.Contains("tor", content, StringComparison.OrdinalIgnoreCase);
- // }
- //}
+ Assert.Contains("tor", content, StringComparison.OrdinalIgnoreCase);
+ }
+ }
- // Unavailable at the time of writing. Not sure if it's even needed.
- //[Fact]
- //public async Task CanRequestOnionV3Async()
- //{
- // using (var client = new TorHttpClient(new Uri("http://dds6qkxpwdeubwucdiaord2xgbbeyds25rbsgr73tbfpqpt4a6vjwsyd.onion"), SharedFixture.TorSocks5Endpoint))
- // {
- // HttpResponseMessage response = await client.SendAsync(HttpMethod.Get, "");
- // var content = await response.Content.ReadAsStringAsync();
+ [Fact]
+ public async Task CanRequestOnionV3Async()
+ {
+ using (var client = new TorHttpClient(new Uri("http://dds6qkxpwdeubwucdiaord2xgbbeyds25rbsgr73tbfpqpt4a6vjwsyd.onion"), SharedFixture.TorSocks5Endpoint))
+ {
+ HttpResponseMessage response = await client.SendAsync(HttpMethod.Get, "");
+ var content = await response.Content.ReadAsStringAsync();
- // Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
- // Assert.Contains("whonix", content, StringComparison.OrdinalIgnoreCase);
- // }
- //}
+ Assert.Contains("whonix", content, StringComparison.OrdinalIgnoreCase);
+ }
+ }
[Fact]
public async Task DoesntIsolateStreamsAsync()

MODIFY
WalletWasabi/Bases/TorDisposableBase.cs
WalletWasabi/Bases/TorDisposableBase.cs
@@ -9,13 +9,13 @@ namespace WalletWasabi.Bases
public TorHttpClient TorClient { get; }
/// <param name="torSocks5EndPoint">if null, then localhost:9050</param>
- protected TorDisposableBase(Uri baseUri, IPEndPoint torSocks5EndPoint = null)
+ protected TorDisposableBase(Uri baseUri, IPEndPoint torSocks5EndPoint)
{
TorClient = new TorHttpClient(baseUri, torSocks5EndPoint, isolateStream: true);
}
/// <param name="torSocks5EndPoint">if null, then localhost:9050</param>
- protected TorDisposableBase(Func<Uri> baseUriAction, IPEndPoint torSocks5EndPoint = null)
+ protected TorDisposableBase(Func<Uri> baseUriAction, IPEndPoint torSocks5EndPoint)
{
TorClient = new TorHttpClient(baseUriAction, torSocks5EndPoint, isolateStream: true);
}

MODIFY
WalletWasabi/Services/CcjClient.cs
WalletWasabi/Services/CcjClient.cs
@@ -68,7 +68,7 @@ namespace WalletWasabi.Services
Network network,
KeyManager keyManager,
Func<Uri> ccjHostUriAction,
- IPEndPoint torSocks5EndPoint = null)
+ IPEndPoint torSocks5EndPoint)
{
Create(synchronizer, network, keyManager, ccjHostUriAction, torSocks5EndPoint);
}
@@ -78,7 +78,7 @@ namespace WalletWasabi.Services
Network network,
KeyManager keyManager,
Uri ccjHostUri,
- IPEndPoint torSocks5EndPoint = null)
+ IPEndPoint torSocks5EndPoint)
{
Create(synchronizer, network, keyManager, () => ccjHostUri, torSocks5EndPoint);
}

MODIFY
WalletWasabi/Services/WasabiSynchronizer.cs
WalletWasabi/Services/WasabiSynchronizer.cs
@@ -167,13 +167,13 @@ namespace WalletWasabi.Services
CreateNew(network, indexFilePath, client);
}
- public WasabiSynchronizer(Network network, string indexFilePath, Func<Uri> baseUriAction, IPEndPoint torSocks5EndPoint = null)
+ public WasabiSynchronizer(Network network, string indexFilePath, Func<Uri> baseUriAction, IPEndPoint torSocks5EndPoint)
{
var client = new WasabiClient(baseUriAction, torSocks5EndPoint);
CreateNew(network, indexFilePath, client);
}
- public WasabiSynchronizer(Network network, string indexFilePath, Uri baseUri, IPEndPoint torSocks5EndPoint = null)
+ public WasabiSynchronizer(Network network, string indexFilePath, Uri baseUri, IPEndPoint torSocks5EndPoint)
{
var client = new WasabiClient(baseUri, torSocks5EndPoint);
CreateNew(network, indexFilePath, client);

MODIFY
WalletWasabi/TorSocks5/TorHttpClient.cs
WalletWasabi/TorSocks5/TorHttpClient.cs
@@ -70,7 +70,7 @@ namespace WalletWasabi.TorSocks5
}
else
{
- TorSocks5EndPoint = torSocks5EndPoint ?? new IPEndPoint(IPAddress.Loopback, 9050);
+ TorSocks5EndPoint = torSocks5EndPoint;
}
TorSocks5Client = null;
IsolateStream = isolateStream;

MODIFY
WalletWasabi/TorSocks5/TorProcessManager.cs
WalletWasabi/TorSocks5/TorProcessManager.cs
@@ -16,7 +16,11 @@ namespace WalletWasabi.TorSocks5
{
public class TorProcessManager : IDisposable
{
+ /// <summary>
+ /// If null then it's just a mock, clearnet is used.
+ /// </summary>
public IPEndPoint TorSocks5EndPoint { get; }
+
public string LogFile { get; }
public static bool RequestFallbackAddressUsage { get; private set; } = false;
@@ -27,15 +31,22 @@ namespace WalletWasabi.TorSocks5
/// <param name="logFile">Opt out of logging with null.</param>
public TorProcessManager(IPEndPoint torSocks5EndPoint, string logFile)
{
- TorSocks5EndPoint = torSocks5EndPoint ?? new IPEndPoint(IPAddress.Loopback, 9050);
+ TorSocks5EndPoint = torSocks5EndPoint;
LogFile = logFile;
_running = 0;
Stop = new CancellationTokenSource();
TorProcess = null;
}
+ public static TorProcessManager Mock() // Mock, don't use Tor at all for debug.
+ {
+ return new TorProcessManager(null, null);
+ }
+
public void Start(bool ensureRunning, string dataDir)
{
+ if (TorSocks5EndPoint == null) return;
+
new Thread(delegate () // Don't ask. This is the only way it worked on Win10/Ubuntu18.04/Manjuro(1 processor VM)/Fedora(1 processor VM)
{
try
@@ -202,6 +213,8 @@ namespace WalletWasabi.TorSocks5
public async Task<bool> IsTorRunningAsync()
{
+ if (TorSocks5EndPoint == null) return true;
+
using (var client = new TorSocks5Client(TorSocks5EndPoint))
{
try
@@ -231,6 +244,8 @@ namespace WalletWasabi.TorSocks5
public void StartMonitor(TimeSpan torMisbehaviorCheckPeriod, TimeSpan checkIfRunningAfterTorMisbehavedFor, string dataDirToStartWith, Uri fallBackTestRequestUri)
{
+ if (TorSocks5EndPoint == null) return;
+
Logger.LogInfo<TorProcessManager>("Starting Tor monitor...");
Interlocked.Exchange(ref _running, 1);
@@ -323,6 +338,9 @@ namespace WalletWasabi.TorSocks5
{
Interlocked.Exchange(ref _running, 2);
}
+
+ if (TorSocks5EndPoint == null) Interlocked.Exchange(ref _running, 3);
+
Stop?.Cancel();
while (IsStopping)
{

MODIFY
WalletWasabi/WebClients/Wasabi/ChaumianCoinJoin/AliceClient.cs
WalletWasabi/WebClients/Wasabi/ChaumianCoinJoin/AliceClient.cs
@@ -40,7 +40,7 @@ namespace WalletWasabi.WebClients.Wasabi.ChaumianCoinJoin
IEnumerable<Requester> requesters,
Network network,
Func<Uri> baseUriAction,
- IPEndPoint torSocks5EndPoint = null) : base(baseUriAction, torSocks5EndPoint)
+ IPEndPoint torSocks5EndPoint) : base(baseUriAction, torSocks5EndPoint)
{
RoundId = roundId;
RegisteredAddresses = registeredAddresses.ToArray();
@@ -57,7 +57,7 @@ namespace WalletWasabi.WebClients.Wasabi.ChaumianCoinJoin
Network network,
InputsRequest request,
Uri baseUri,
- IPEndPoint torSocks5EndPoint = null)
+ IPEndPoint torSocks5EndPoint)
{
return await CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, request, () => baseUri, torSocks5EndPoint);
}
@@ -123,7 +123,7 @@ namespace WalletWasabi.WebClients.Wasabi.ChaumianCoinJoin
IEnumerable<uint256> blindedOutputScriptHashes,
IEnumerable<InputProofModel> inputs,
Uri baseUri,
- IPEndPoint torSocks5EndPoint = null)
+ IPEndPoint torSocks5EndPoint)
{
return await CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, changeOutput, blindedOutputScriptHashes, inputs, () => baseUri, torSocks5EndPoint);
}

MODIFY
WalletWasabi/WebClients/Wasabi/ChaumianCoinJoin/BobClient.cs
WalletWasabi/WebClients/Wasabi/ChaumianCoinJoin/BobClient.cs
@@ -13,12 +13,12 @@ namespace WalletWasabi.WebClients.Wasabi.ChaumianCoinJoin
public class BobClient : TorDisposableBase
{
/// <inheritdoc/>
- public BobClient(Func<Uri> baseUriAction, IPEndPoint torSocks5EndPoint = null) : base(baseUriAction, torSocks5EndPoint)
+ public BobClient(Func<Uri> baseUriAction, IPEndPoint torSocks5EndPoint) : base(baseUriAction, torSocks5EndPoint)
{
}
/// <inheritdoc/>
- public BobClient(Uri baseUri, IPEndPoint torSocks5EndPoint = null) : base(baseUri, torSocks5EndPoint)
+ public BobClient(Uri baseUri, IPEndPoint torSocks5EndPoint) : base(baseUri, torSocks5EndPoint)
{
}

MODIFY
WalletWasabi/WebClients/Wasabi/ChaumianCoinJoin/SatoshiClient.cs
WalletWasabi/WebClients/Wasabi/ChaumianCoinJoin/SatoshiClient.cs
@@ -13,12 +13,12 @@ namespace WalletWasabi.WebClients.Wasabi.ChaumianCoinJoin
public class SatoshiClient : TorDisposableBase
{
/// <inheritdoc/>
- public SatoshiClient(Func<Uri> baseUriAction, IPEndPoint torSocks5EndPoint = null) : base(baseUriAction, torSocks5EndPoint)
+ public SatoshiClient(Func<Uri> baseUriAction, IPEndPoint torSocks5EndPoint) : base(baseUriAction, torSocks5EndPoint)
{
}
/// <inheritdoc/>
- public SatoshiClient(Uri baseUri, IPEndPoint torSocks5EndPoint = null) : base(baseUri, torSocks5EndPoint)
+ public SatoshiClient(Uri baseUri, IPEndPoint torSocks5EndPoint) : base(baseUri, torSocks5EndPoint)
{
}

MODIFY
WalletWasabi/WebClients/Wasabi/WasabiClient.cs
WalletWasabi/WebClients/Wasabi/WasabiClient.cs
@@ -17,12 +17,12 @@ namespace WalletWasabi.WebClients.Wasabi
public class WasabiClient : TorDisposableBase
{
/// <inheritdoc/>
- public WasabiClient(Func<Uri> baseUriAction, IPEndPoint torSocks5EndPoint = null) : base(baseUriAction, torSocks5EndPoint)
+ public WasabiClient(Func<Uri> baseUriAction, IPEndPoint torSocks5EndPoint) : base(baseUriAction, torSocks5EndPoint)
{
}
/// <inheritdoc/>
- public WasabiClient(Uri baseUri, IPEndPoint torSocks5EndPoint = null) : base(baseUri, torSocks5EndPoint)
+ public WasabiClient(Uri baseUri, IPEndPoint torSocks5EndPoint) : base(baseUri, torSocks5EndPoint)
{
}

Add clearnet debugging feature. Closes https://github.com/zkSNACKs/WalletWasabi/issues/996