Use SafeIoManager when save/load wallet files
MODIFY
WalletWasabi/Blockchain/Keys/KeyManager.cs
WalletWasabi/Blockchain/Keys/KeyManager.cs
@@ -10,6 +10,7 @@ using System.Security;
using System.Text;
using WalletWasabi.Blockchain.Analysis.Clustering;
using WalletWasabi.Helpers;
+using WalletWasabi.Io;
using WalletWasabi.JsonConverters;
using WalletWasabi.Logging;
using WalletWasabi.Models;
@@ -194,7 +195,9 @@ namespace WalletWasabi.Blockchain.Keys
throw new FileNotFoundException($"Wallet file not found at: `{filePath}`.");
}
- string jsonString = File.ReadAllText(filePath, Encoding.UTF8);
+ SafeIoManager safeIoManager = new(filePath);
+ string jsonString = safeIoManager.ReadAllText(Encoding.UTF8);
+
var km = JsonConvert.DeserializeObject<KeyManager>(jsonString);
km.SetFilePath(filePath);
@@ -587,7 +590,9 @@ namespace WalletWasabi.Blockchain.Keys
BlockchainState.Height = new Height(matureHeight);
string jsonString = JsonConvert.SerializeObject(this, Formatting.Indented);
- File.WriteAllText(filePath, jsonString, Encoding.UTF8);
+
+ SafeIoManager safeIoManager = new(filePath);
+ safeIoManager.WriteAllText(jsonString, Encoding.UTF8);
// Re-add removed items for further operations.
BlockchainState.Height = prevHeight;

MODIFY
WalletWasabi/Io/SafeIoManager.cs
WalletWasabi/Io/SafeIoManager.cs
@@ -2,6 +2,7 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
+using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WalletWasabi.Helpers;
@@ -136,6 +137,19 @@ namespace WalletWasabi.Io
SafeMoveNewToOriginal();
}
+ public void WriteAllText(string text, Encoding encoding)
+ {
+ if (string.IsNullOrEmpty(text))
+ {
+ return;
+ }
+
+ IoHelpers.EnsureContainingDirectoryExists(NewFilePath);
+
+ File.WriteAllText(NewFilePath, text, encoding);
+ SafeMoveNewToOriginal();
+ }
+
public new async Task<string[]> ReadAllLinesAsync(CancellationToken cancellationToken = default)
{
var filePath = FilePath;
@@ -146,6 +160,17 @@ namespace WalletWasabi.Io
return await ReadAllLinesAsync(filePath, cancellationToken).ConfigureAwait(false);
}
+ public string ReadAllText(Encoding encoding)
+ {
+ var filePath = FilePath;
+ if (TryGetSafestFileVersion(out string? safestFilePath))
+ {
+ filePath = safestFilePath;
+ }
+
+ return File.ReadAllText(filePath, encoding);
+ }
+
/// <summary>
/// Open text file and read a specified amount of data. This method is useful when you want async/await read/write
/// but in a performant way.

Use SafeIoManager when save/load wallet files