Start implementing daemon again
MODIFY
WalletWasabi.Gui/CommandLine/Daemon.cs
WalletWasabi.Gui/CommandLine/Daemon.cs
@@ -6,6 +6,7 @@ using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using WalletWasabi.Helpers;
+using WalletWasabi.KeyManagement;
using WalletWasabi.Logging;
namespace WalletWasabi.Gui.CommandLine
@@ -18,6 +19,8 @@ namespace WalletWasabi.Gui.CommandLine
var printConsole = false;
var showVersion = false;
LogLevel? logLevel = null;
+ string walletName = null;
+ var doMix = false;
try
{
@@ -32,7 +35,7 @@ namespace WalletWasabi.Gui.CommandLine
{ "h|help", "Displays help page and exit.", x => showHelp = x != null},
{ "p|printconsole", "Log to the standard output", x => printConsole = x != null},
{ "l|loglevel=", "Sets the level of verbosity for the log TRACE|INFO|WARN|DEBUG|ERROR.", x => {
- var normalized = x.ToLower().Trim();
+ var normalized = x?.ToLower()?.Trim();
if(normalized == "info") logLevel = LogLevel.Info;
else if(normalized == "warn") logLevel = LogLevel.Warning;
else if(normalized == "error") logLevel = LogLevel.Error;
@@ -43,6 +46,10 @@ namespace WalletWasabi.Gui.CommandLine
showHelp = true;
}
}},
+ { "m|mix", "Start mixing without the GUI with the specified wallet.", x => doMix = x != null},
+ { "w|wallet=", "The specified wallet file.", x => {
+ walletName = x?.ToLower()?.Trim();
+ }}
};
try
{
@@ -77,8 +84,10 @@ namespace WalletWasabi.Gui.CommandLine
finally
{
if (!printConsole)
+ {
Native.DettachParentConsole();
}
+ }
Logger.InitializeDefaults(Path.Combine(Global.DataDir, "Logs.txt"));
@@ -91,6 +100,39 @@ namespace WalletWasabi.Gui.CommandLine
Logger.Modes.Add(LogMode.Console);
}
continueWithGui = true;
+
+ KeyManager keyManager = null;
+ if (walletName != null)
+ {
+ continueWithGui = false;
+
+ var walletFullPath = Global.GetWalletFullPath(walletName);
+ var walletBackupFullPath = Global.GetWalletBackupFullPath(walletName);
+ if (!File.Exists(walletFullPath) && !File.Exists(walletBackupFullPath))
+ {
+ // The selected wallet is not available any more (someone deleted it?).
+ Console.WriteLine("The selected wallet doesn't exsist, did you delete it?");
+ return;
+ }
+
+ try
+ {
+ keyManager = Global.LoadKeyManager(walletFullPath, walletBackupFullPath);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex);
+ return;
+ }
+ }
+
+ if (doMix)
+ {
+ if (keyManager == null)
+ {
+ Console.WriteLine("Wallet is not supplied.");
+ }
+ }
}
private static void ShowVersion()

MODIFY
WalletWasabi.Gui/Global.cs
WalletWasabi.Gui/Global.cs
@@ -65,6 +65,7 @@ namespace WalletWasabi.Gui
public static string AddressManagerFilePath { get; private set; }
public static AddressManager AddressManager { get; private set; }
public static MemPoolService MemPoolService { get; private set; }
+
public static NodesGroup Nodes { get; private set; }
public static WasabiSynchronizer Synchronizer { get; private set; }
public static CcjClient ChaumianClient { get; private set; }
@@ -132,6 +133,18 @@ namespace WalletWasabi.Gui
}
}
+ public static async Task InitializeNoUiAsync()
+ {
+ var configFilePath = Path.Combine(DataDir, "Config.json");
+ var config = new Config(configFilePath);
+ await config.LoadOrCreateDefaultFileAsync();
+ Logger.LogInfo<Config>("Config is successfully initialized.");
+
+ InitializeConfig(config);
+
+ InitializeNoWallet();
+ }
+
public static void InitializeNoWallet()
{
WalletService = null;
@@ -257,7 +270,7 @@ namespace WalletWasabi.Gui
Nodes.Connect();
Logger.LogInfo("Start connecting to nodes...");
- if (!(RegTestMemPoolServingNode is null))
+ if (RegTestMemPoolServingNode != null)
{
RegTestMemPoolServingNode.VersionHandshake();
Logger.LogInfo("Start connecting to mempool serving regtest node...");
@@ -295,6 +308,66 @@ namespace WalletWasabi.Gui
WalletService.Coins.CollectionChanged += Coins_CollectionChanged;
}
+ public static string GetWalletFullPath(string walletName)
+ {
+ walletName = walletName.TrimEnd(".json", StringComparison.OrdinalIgnoreCase);
+ return Path.Combine(WalletsDir, walletName + ".json");
+ }
+
+ public static string GetWalletBackupFullPath(string walletName)
+ {
+ walletName = walletName.TrimEnd(".json", StringComparison.OrdinalIgnoreCase);
+ return Path.Combine(WalletBackupsDir, walletName + ".json");
+ }
+
+ public static KeyManager LoadKeyManager(string walletFullPath, string walletBackupFullPath)
+ {
+ try
+ {
+ return LoadKeyManager(walletFullPath);
+ }
+ catch (Exception ex)
+ {
+ if (!File.Exists(walletBackupFullPath))
+ {
+ throw;
+ }
+
+ Logger.LogWarning($"Wallet got corrupted.\n" +
+ $"Wallet Filepath: {walletFullPath}\n" +
+ $"Trying to recover it from backup.\n" +
+ $"Backup path: {walletBackupFullPath}\n" +
+ $"Exception: {ex.ToString()}");
+ if (File.Exists(walletFullPath))
+ {
+ string corruptedWalletBackupPath = Path.Combine(WalletBackupsDir, $"{Path.GetFileName(walletFullPath)}_CorruptedBackup");
+ if (File.Exists(corruptedWalletBackupPath))
+ {
+ File.Delete(corruptedWalletBackupPath);
+ Logger.LogInfo($"Deleted previous corrupted wallet file backup from {corruptedWalletBackupPath}.");
+ }
+ File.Move(walletFullPath, corruptedWalletBackupPath);
+ Logger.LogInfo($"Backed up corrupted wallet file to {corruptedWalletBackupPath}.");
+ }
+ File.Copy(walletBackupFullPath, walletFullPath);
+
+ return LoadKeyManager(walletFullPath);
+ }
+ }
+
+ public static KeyManager LoadKeyManager(string walletFullPath)
+ {
+ KeyManager keyManager;
+ var walletFileInfo = new FileInfo(walletFullPath)
+ {
+ LastAccessTime = DateTime.Now
+ };
+
+ keyManager = KeyManager.FromFile(walletFullPath);
+ Logger.LogInfo($"Wallet loaded: {Path.GetFileNameWithoutExtension(keyManager.FilePath)}.");
+ return keyManager;
+ }
+
private static void Coins_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
try

MODIFY
WalletWasabi.Gui/Program.cs
WalletWasabi.Gui/Program.cs
@@ -39,14 +39,8 @@ namespace WalletWasabi.Gui
{
MainWindowViewModel.Instance = new MainWindowViewModel();
- var configFilePath = Path.Combine(Global.DataDir, "Config.json");
- var config = new Config(configFilePath);
- await config.LoadOrCreateDefaultFileAsync();
- Logger.LogInfo<Config>("Config is successfully initialized.");
+ await Global.InitializeNoUiAsync();
- Global.InitializeConfig(config);
-
- Global.InitializeNoWallet();
statusBar = new StatusBarViewModel(Global.Nodes.ConnectedNodes, Global.Synchronizer, Global.UpdateChecker);
MainWindowViewModel.Instance.StatusBar = statusBar;

MODIFY
WalletWasabi.Gui/Tabs/WalletManager/LoadWalletViewModel.cs
WalletWasabi.Gui/Tabs/WalletManager/LoadWalletViewModel.cs
@@ -236,8 +236,8 @@ namespace WalletWasabi.Gui.Tabs.WalletManager
return null;
}
- var walletFullPath = Path.Combine(Global.WalletsDir, SelectedWallet + ".json");
- var walletBackupFullPath = Path.Combine(Global.WalletBackupsDir, SelectedWallet + ".json");
+ var walletFullPath = Global.GetWalletFullPath(SelectedWallet);
+ var walletBackupFullPath = Global.GetWalletBackupFullPath(SelectedWallet);
if (!File.Exists(walletFullPath) && !File.Exists(walletBackupFullPath))
{
// The selected wallet is not available any more (someone deleted it?).
@@ -246,38 +246,7 @@ namespace WalletWasabi.Gui.Tabs.WalletManager
return null;
}
- KeyManager keyManager = null;
- try
- {
- keyManager = LoadKeyManager(walletFullPath);
- }
- catch (Exception ex)
- {
- if (!File.Exists(walletBackupFullPath))
- {
- throw;
- }
-
- Logger.LogWarning($"Wallet got corrupted.\n" +
- $"Wallet Filepath: {walletFullPath}\n" +
- $"Trying to recover it from backup.\n" +
- $"Backup path: {walletBackupFullPath}\n" +
- $"Exception: {ex.ToString()}");
- if (File.Exists(walletFullPath))
- {
- string corruptedWalletBackupPath = Path.Combine(Global.WalletBackupsDir, $"{Path.GetFileName(walletFullPath)}_CorruptedBackup");
- if (File.Exists(corruptedWalletBackupPath))
- {
- File.Delete(corruptedWalletBackupPath);
- Logger.LogInfo($"Deleted previous corrupted wallet file backup from {corruptedWalletBackupPath}.");
- }
- File.Move(walletFullPath, corruptedWalletBackupPath);
- Logger.LogInfo($"Backed up corrupted wallet file to {corruptedWalletBackupPath}.");
- }
- File.Copy(walletBackupFullPath, walletFullPath);
-
- keyManager = LoadKeyManager(walletFullPath);
- }
+ KeyManager keyManager = Global.LoadKeyManager(walletFullPath, walletBackupFullPath);
// Only check requirepassword here, because the above checks are applicable to loadwallet, too and we are using this function from load wallet.
if (requirePassword)
@@ -355,19 +324,6 @@ namespace WalletWasabi.Gui.Tabs.WalletManager
}
}
- private KeyManager LoadKeyManager(string walletFullPath)
- {
- KeyManager keyManager;
- var walletFileInfo = new FileInfo(walletFullPath)
- {
- LastAccessTime = DateTime.Now
- };
-
- keyManager = KeyManager.FromFile(walletFullPath);
- Logger.LogInfo($"Wallet decrypted: {SelectedWallet}.");
- return keyManager;
- }
-
public ReactiveCommand OpenFolderCommand { get; }
public void OpenWalletsFolder()

MODIFY
WalletWasabi/Helpers/IoHelpers.cs
WalletWasabi/Helpers/IoHelpers.cs
@@ -200,6 +200,29 @@ namespace System.IO
}
}
+ /// <summary>
+ /// https://stackoverflow.com/a/479198/2061103
+ /// This is a pretty simple implementation that assumes that the file and directories all exist and are accessible:
+ /// </summary>
+ public static string GetProperDirectoryCapitalization(DirectoryInfo dirInfo)
+ {
+ DirectoryInfo parentDirInfo = dirInfo.Parent;
+ return null == parentDirInfo
+ ? dirInfo.Name
+ : Path.Combine(GetProperDirectoryCapitalization(parentDirInfo), parentDirInfo.GetDirectories(dirInfo.Name)[0].Name);
+ }
+
+ /// <summary>
+ /// https://stackoverflow.com/a/479198/2061103
+ /// This is a pretty simple implementation that assumes that the file and directories all exist and are accessible:
+ /// </summary>
+ public static string GetProperFilePathCapitalization(string filename)
+ {
+ FileInfo fileInfo = new FileInfo(filename);
+ DirectoryInfo dirInfo = fileInfo.Directory;
+ return Path.Combine(GetProperDirectoryCapitalization(dirInfo), dirInfo.GetFiles(fileInfo.Name)[0].Name);
+ }
+
// https://stackoverflow.com/a/7957634/2061103
public static bool TryGetSafestFileVersion(string path, out string safestFilePath)
{
@@ -209,27 +232,27 @@ namespace System.IO
// If foo.data and foo.data.new exist, load foo.data; foo.data.new may be broken (e.g. power off during write).
if (File.Exists(path) && File.Exists(newPath))
{
- safestFilePath = path;
+ safestFilePath = GetProperFilePathCapitalization(path);
return true;
}
// If foo.data.old and foo.data.new exist, both should be valid, but something died very shortly afterwards - you may want to load the foo.data.old version anyway.
if (File.Exists(oldPath) && File.Exists(newPath))
{
- safestFilePath = oldPath;
+ safestFilePath = GetProperFilePathCapitalization(oldPath);
return true;
}
// If foo.data and foo.data.old exist, then foo.data should be fine, but again something went wrong, or possibly the file couldn't be deleted.
if (File.Exists(oldPath) && File.Exists(path))
{
- safestFilePath = path;
+ safestFilePath = GetProperFilePathCapitalization(path);
return true;
}
if (File.Exists(path))
{
- safestFilePath = path;
+ safestFilePath = GetProperFilePathCapitalization(path);
return true;
}

MODIFY
WalletWasabi/KeyManagement/KeyManager.cs
WalletWasabi/KeyManagement/KeyManager.cs
@@ -153,6 +153,16 @@ namespace WalletWasabi.KeyManagement
throw new FileNotFoundException($"Wallet file not found at: `{filePath}`.");
}
+ // Try recase if doesn't succeed, then go with the supplied casing.
+ try
+ {
+ filePath = IoHelpers.GetProperFilePathCapitalization(filePath);
+ }
+ catch
+ {
+ // Ignored.
+ }
+
string jsonString = File.ReadAllText(safestFile, Encoding.UTF8);
var km = JsonConvert.DeserializeObject<KeyManager>(jsonString);
km.SetFilePath(filePath);

Start implementing daemon again