Separate persistent methods
Removes redundant calls to `ToFile()`. In tests we almost never want to persist the keys so, no need to call persisten methods.
MODIFY
WalletWasabi.Fluent/Rpc/WasabiJsonRpcService.cs
WalletWasabi.Fluent/Rpc/WasabiJsonRpcService.cs
@@ -116,7 +116,7 @@ public class WasabiJsonRpcService : IJsonRpcService
var activeWallet = Guard.NotNull(nameof(ActiveWallet), ActiveWallet);
var hdkey = activeWallet.KeyManager
- .GenerateNewKey(new SmartLabel(label), KeyState.Clean, isInternal: false);
+ .GenerateNewPersistentKey(new SmartLabel(label), KeyState.Clean, isInternal: false);
return new
{
address = hdkey.GetP2wpkhAddress(Global.Network).ToString(),

MODIFY
WalletWasabi.Tests/Helpers/ServiceFactory.cs
WalletWasabi.Tests/Helpers/ServiceFactory.cs
@@ -27,7 +27,7 @@ public static class ServiceFactory
var toGenerate = coinArray.Length - generated;
for (int i = 0; i < toGenerate; i++)
{
- keyManager.GenerateNewKey("", KeyState.Clean, false, false);
+ keyManager.GenerateNewKey("", KeyState.Clean, false);
}
var keys = keyManager.GetKeys().Take(coinArray.Length).ToArray();

MODIFY
WalletWasabi.Tests/UnitTests/KeyManagementTests.cs
WalletWasabi.Tests/UnitTests/KeyManagementTests.cs
@@ -80,7 +80,7 @@ public class KeyManagementTests
Assert.NotEqual(manager.ExtPubKey, differentManager.ExtPubKey);
differentManager.AssertCleanKeysIndexed();
- var newKey = differentManager.GenerateNewKey("some-label", KeyState.Clean, true, false);
+ var newKey = differentManager.GenerateNewKey("some-label", KeyState.Clean, true);
Assert.Equal(newKey.Index, differentManager.MinGapLimit);
Assert.Equal("999'/999'/999'/1/55", newKey.FullKeyPath.ToString());
}
@@ -122,7 +122,7 @@ public class KeyManagementTests
var isInternal = Random.Shared.Next(2) == 0;
var label = RandomString.AlphaNumeric(21);
var keyState = (KeyState)Random.Shared.Next(3);
- manager.GenerateNewKey(label, keyState, isInternal, toFile: false);
+ manager.GenerateNewKey(label, keyState, isInternal);
}
manager.ToFile();

MODIFY
WalletWasabi.Tests/UnitTests/Transactions/TransactionFactoryTests.cs
WalletWasabi.Tests/UnitTests/Transactions/TransactionFactoryTests.cs
@@ -184,7 +184,7 @@ public class TransactionFactoryTests
keyManager.AssertCleanKeysIndexed();
- HdPubKey NewKey(string label) => keyManager.GenerateNewKey(label, KeyState.Used, true, false);
+ HdPubKey NewKey(string label) => keyManager.GenerateNewKey(label, KeyState.Used, true);
var scoins = new[]
{
BitcoinFactory.CreateSmartCoin(NewKey("Pablo"), 0.9m),

MODIFY
WalletWasabi.Tests/UnitTests/UserInterfaceTest/LabelTestExtensions.cs
WalletWasabi.Tests/UnitTests/UserInterfaceTest/LabelTestExtensions.cs
@@ -28,7 +28,7 @@ internal static class LabelTestExtensions
public static HdPubKey NewKey(string label = "", int anonymitySet = 1)
{
- var key = KeyManager.GenerateNewKey(label, KeyState.Used, true, false);
+ var key = KeyManager.GenerateNewKey(label, KeyState.Used, true);
key.SetAnonymitySet(anonymitySet);
key.SetLabel(label);

MODIFY
WalletWasabi/Blockchain/Keys/KeyManager.cs
WalletWasabi/Blockchain/Keys/KeyManager.cs
@@ -313,7 +313,14 @@ public class KeyManager
}
}
- public HdPubKey GenerateNewKey(SmartLabel label, KeyState keyState, bool isInternal, bool toFile = true)
+ public HdPubKey GenerateNewPersistentKey(SmartLabel label, KeyState keyState, bool isInternal)
+ {
+ var newKey = GenerateNewKey(label, keyState, isInternal);
+ ToFile();
+ return newKey;
+ }
+
+ public HdPubKey GenerateNewKey(SmartLabel label, KeyState keyState, bool isInternal)
{
// BIP44-ish derivation scheme
// m / purpose' / coin_type' / account' / change / address_index
@@ -360,11 +367,6 @@ public class KeyManager
ScriptHdPubKeyMap.Add(hdPubKey.P2wpkhScript, hdPubKey);
}
- if (toFile)
- {
- ToFile();
- }
-
return hdPubKey;
}
}
@@ -578,7 +580,18 @@ public class KeyManager
/// Make sure there's always clean keys generated and indexed.
/// Call SetMinGapLimit() to set how many keys should be asserted.
/// </summary>
- public IEnumerable<HdPubKey> AssertCleanKeysIndexed(bool? isInternal = null, bool toFile = true)
+ public IEnumerable<HdPubKey> AssertCleanKeysIndexedAndPersist(bool? isInternal = null)
+ {
+ var newKeys = AssertCleanKeysIndexed(isInternal);
+ if (newKeys.Any())
+ {
+ ToFile();
+ }
+
+ return newKeys;
+ }
+
+ public IEnumerable<HdPubKey> AssertCleanKeysIndexed(bool? isInternal = null)
{
var newKeys = new List<HdPubKey>();
@@ -586,32 +599,35 @@ public class KeyManager
{
while (CountConsecutiveUnusedKeys(isInternal.Value, ignoreTail: false) < MinGapLimit)
{
- newKeys.Add(GenerateNewKey(SmartLabel.Empty, KeyState.Clean, isInternal.Value, toFile: false));
+ newKeys.Add(GenerateNewKey(SmartLabel.Empty, KeyState.Clean, isInternal.Value));
}
}
else
{
while (CountConsecutiveUnusedKeys(true, ignoreTail: false) < MinGapLimit)
{
- newKeys.Add(GenerateNewKey(SmartLabel.Empty, KeyState.Clean, true, toFile: false));
+ newKeys.Add(GenerateNewKey(SmartLabel.Empty, KeyState.Clean, true));
}
while (CountConsecutiveUnusedKeys(false, ignoreTail: false) < MinGapLimit)
{
- newKeys.Add(GenerateNewKey(SmartLabel.Empty, KeyState.Clean, false, toFile: false));
+ newKeys.Add(GenerateNewKey(SmartLabel.Empty, KeyState.Clean, false));
}
}
- if (toFile && newKeys.Any())
- {
- ToFile();
- }
-
return newKeys;
}
/// <summary>
/// Make sure there's always locked internal keys generated and indexed.
/// </summary>
+ public void AssertLockedInternalKeysIndexedAndPersist(int howMany)
+ {
+ if (AssertLockedInternalKeysIndexed(howMany))
+ {
+ ToFile();
+ }
+ }
+
public bool AssertLockedInternalKeysIndexed(int howMany)
{
var changed = false;
@@ -623,7 +639,7 @@ public class KeyManager
if (firstUnusedInternalKey is null)
{
// If not found, generate a new.
- GenerateNewKey(SmartLabel.Empty, KeyState.Locked, true, toFile: false);
+ GenerateNewKey(SmartLabel.Empty, KeyState.Locked, true);
}
else
{
@@ -633,14 +649,9 @@ public class KeyManager
changed = true;
}
- AssertCleanKeysIndexed(isInternal: true, toFile: false);
-
- if (changed)
- {
- ToFile();
- }
+ var newKeys = AssertCleanKeysIndexed(isInternal: true);
- return changed;
+ return changed || newKeys.Any();
}
private void SetMinGapLimit(int? minGapLimit)

MODIFY
WalletWasabi/Blockchain/TransactionProcessing/TransactionProcessor.cs
WalletWasabi/Blockchain/TransactionProcessing/TransactionProcessor.cs
@@ -237,7 +237,7 @@ public class TransactionProcessor
result.NewlyReceivedCoins.Add(newCoin);
// Make sure there's always 21 clean keys generated and indexed.
- KeyManager.AssertCleanKeysIndexed(isInternal: foundKey.IsInternal);
+ KeyManager.AssertCleanKeysIndexedAndPersist(isInternal: foundKey.IsInternal);
}
else // If we had this coin already.
{

MODIFY
WalletWasabi/Blockchain/Transactions/TransactionFactory.cs
WalletWasabi/Blockchain/Transactions/TransactionFactory.cs
@@ -143,7 +143,7 @@ public class TransactionFactory
}
else
{
- KeyManager.AssertCleanKeysIndexed(isInternal: true);
+ KeyManager.AssertCleanKeysIndexedAndPersist(isInternal: true);
changeHdPubKey = KeyManager.GetKeys(KeyState.Clean, true).First();
builder.SetChange(changeHdPubKey.P2wpkhScript);

MODIFY
WalletWasabi/WabiSabi/Client/InternalDestinationProvider.cs
WalletWasabi/WabiSabi/Client/InternalDestinationProvider.cs
@@ -17,7 +17,7 @@ public class InternalDestinationProvider : IDestinationProvider
public IEnumerable<IDestination> GetNextDestinations(int count)
{
// Get all locked internal keys we have and assert we have enough.
- KeyManager.AssertLockedInternalKeysIndexed(count);
+ KeyManager.AssertLockedInternalKeysIndexedAndPersist(count);
return KeyManager.GetKeys(x => x.IsInternal && x.KeyState == KeyState.Locked).Select(x => x.PubKey.WitHash);
}
}

MODIFY
WalletWasabi/Wallets/Wallet.cs
WalletWasabi/Wallets/Wallet.cs
@@ -41,7 +41,7 @@ public class Wallet : BackgroundService, IWallet
RuntimeParams.SetDataDir(dataDir);
HandleFiltersLock = new AsyncLock();
- KeyManager.AssertCleanKeysIndexed();
+ KeyManager.AssertCleanKeysIndexedAndPersist();
if (!KeyManager.IsWatchOnly)
{

Separate persistent methods (#8996)

Removes redundant calls to `ToFile()`. In tests we almost never want to persist the keys so, no need to call persisten methods.