Make sure to fill the keys gap
MODIFY
WalletWasabi.Tests/UnitTests/KeyManagementTests.cs
WalletWasabi.Tests/UnitTests/KeyManagementTests.cs
using NBitcoin;
using System;
using System.IO;
+using System.Linq;
using System.Security;
using WalletWasabi.Blockchain.Analysis.Clustering;
using WalletWasabi.Blockchain.Keys;
@@ -85,6 +86,19 @@ namespace WalletWasabi.Tests.UnitTests
Assert.Equal("999'/999'/999'/1/55", newKey.FullKeyPath.ToString());
}
+ [Fact]
+ public void CanHandleGap()
+ {
+ string password = "password";
+ var manager = KeyManager.CreateNew(out Mnemonic mnemonic, password);
+
+ manager.AssertCleanKeysIndexed();
+ var lastKey = manager.GetKeys(KeyState.Clean, isInternal: false).Last();
+ lastKey.SetKeyState(KeyState.Used);
+ var newKeys = manager.AssertCleanKeysIndexed();
+ Assert.Equal(manager.MinGapLimit, newKeys.Count());
+ }
+
[Fact]
public void CanSerialize()
{

MODIFY
WalletWasabi/Blockchain/Keys/KeyManager.cs
WalletWasabi/Blockchain/Keys/KeyManager.cs
@@ -530,6 +530,33 @@ namespace WalletWasabi.Blockchain.Keys
}
}
+ public int GetConsecutiveKeysCount(KeyState? keyState = null, bool? isInternal = null)
+ {
+ var keys = GetKeys(KeyState.Clean, isInternal);
+ var keyCount = keys.Count();
+ if (keyCount < 2) return keyCount;
+
+ var largerConsecutiveSequence = 1;
+ var consecutives = 1;
+ for(int i = 1; i < keyCount; i++)
+ {
+ if(keys.ElementAt(i).Index == keys.ElementAt(i-1).Index + 1)
+ {
+ consecutives++;
+ }
+ else
+ {
+ if(consecutives > largerConsecutiveSequence)
+ {
+ largerConsecutiveSequence = consecutives;
+ consecutives = 1;
+ }
+ }
+ }
+
+ return Math.Max(consecutives, largerConsecutiveSequence);
+ }
+
public IEnumerable<byte[]> GetPubKeyScriptBytes()
{
lock (HdPubKeyScriptBytesLock)
@@ -617,18 +644,18 @@ namespace WalletWasabi.Blockchain.Keys
if (isInternal is null)
{
- while (GetKeys(KeyState.Clean, true).Count() < MinGapLimit)
+ while (GetConsecutiveKeysCount(KeyState.Clean, true) < MinGapLimit)
{
newKeys.Add(GenerateNewKey(SmartLabel.Empty, KeyState.Clean, true, toFile: false));
}
- while (GetKeys(KeyState.Clean, false).Count() < MinGapLimit)
+ while (GetConsecutiveKeysCount(KeyState.Clean, false) < MinGapLimit)
{
newKeys.Add(GenerateNewKey(SmartLabel.Empty, KeyState.Clean, false, toFile: false));
}
}
else
{
- while (GetKeys(KeyState.Clean, isInternal).Count() < MinGapLimit)
+ while (GetConsecutiveKeysCount(KeyState.Clean, isInternal) < MinGapLimit)
{
newKeys.Add(GenerateNewKey(SmartLabel.Empty, KeyState.Clean, (bool)isInternal, toFile: false));
}

Make sure to fill the keys gap