From ccd1591503bfbb04811186fcab791c05ccd176f6 Mon Sep 17 00:00:00 2001 From: Rodrigo <39995243+RodriFS@users.noreply.github.com> Date: Wed, 18 Oct 2023 18:54:44 +0200 Subject: [PATCH] Hotfix: Unable to create wallets (#323) * Hotfix: Unable to create wallets * Fixed unit tests --- src/Data/Repositories/WalletRepository.cs | 40 +++++++++---------- .../Repositories/WalletRepositoryTests.cs | 17 +++++--- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/Data/Repositories/WalletRepository.cs b/src/Data/Repositories/WalletRepository.cs index aef0037a..1e333871 100644 --- a/src/Data/Repositories/WalletRepository.cs +++ b/src/Data/Repositories/WalletRepository.cs @@ -104,12 +104,12 @@ public async Task> GetAvailableWallets(bool includeWatchOnlyWallets .Include(x => x.InternalWallet) .Include(x => x.Keys) .ToListAsync(); - + if (!includeWatchOnlyWallets) { availableWallets = availableWallets.Where(w => !w.IsWatchOnly).ToList(); } - + return availableWallets; } @@ -120,11 +120,11 @@ public async Task> GetAvailableWallets(bool includeWatchOnlyWallets type.SetCreationDatetime(); type.SetUpdateDatetime(); - + if (type.IsBIP39Imported || type.IsWatchOnly) { //Persist - + var addResult = await _repository.AddAsync(type, applicationDbContext); return addResult; @@ -134,7 +134,7 @@ public async Task> GetAvailableWallets(bool includeWatchOnlyWallets { //We add the internal wallet of the moment and its key if it is not a BIP39 wallet - + var currentInternalWallet = (await _internalWalletRepository.GetCurrentInternalWallet()); if (currentInternalWallet != null) { @@ -149,7 +149,7 @@ public async Task> GetAvailableWallets(bool includeWatchOnlyWallets type.Keys = new List(); var addResult = await _repository.AddAsync(type, applicationDbContext); - + if (!addResult.Item1) return addResult; @@ -230,7 +230,7 @@ public async Task GetNextSubderivationPath() { await using var applicationDbContext = await _dbContextFactory.CreateDbContextAsync(); - var lastWallet = applicationDbContext.Wallets.OrderBy(w => w.Id).LastOrDefault(w => w.IsFinalised && !w.IsBIP39Imported); + var lastWallet = applicationDbContext.Wallets.OrderBy(w => w.Id).LastOrDefault(w => w.IsFinalised && !w.IsBIP39Imported && w.InternalWalletMasterFingerprint != null); if (lastWallet == null || string.IsNullOrEmpty(lastWallet.InternalWalletSubDerivationPath)) return "0"; @@ -289,10 +289,10 @@ public async Task GetNextSubderivationPath() try { - + //Validate derivation path var keyPath = KeyPath.Parse(derivationPath); - + //Mnenomic create var mnemonic = new Mnemonic(seedphrase); @@ -334,7 +334,7 @@ public async Task GetNextSubderivationPath() return (false, addResult.Item2); } - //Create key + //Create key var key = new Key { CreationDatetime = DateTimeOffset.Now, @@ -388,15 +388,15 @@ public async Task GetNextSubderivationPath() } public async Task TrackAndScanWallet(Wallet wallet){ - + var derivationStrategyBase = wallet.GetDerivationStrategy(); if (derivationStrategyBase == null) { _logger.LogError("Error while getting the derivation scheme"); - + throw new InvalidOperationException("Error while getting the derivation scheme for wallet with id: when rescaning" + wallet.Id); } - + _logger.LogInformation("Starting tracking and scanning wallet with id: {WalletId}", wallet.Id); //Track wallet @@ -415,7 +415,7 @@ public async Task TrackAndScanWallet(Wallet wallet){ throw new ArgumentException("Value cannot be null or whitespace.", nameof(outputDescriptor)); (bool, string?) result = (true, null); - + try { var (strategyBase, tuples) = WalletParser.ParseOutputDescriptor(outputDescriptor, CurrentNetworkHelper.GetCurrentNetwork()); @@ -431,9 +431,9 @@ public async Task TrackAndScanWallet(Wallet wallet){ Path = x.Item2.KeyPath.ToString(), IsBIP39ImportedKey = false, UserId = userId, - + }).ToList(); - + Wallet? wallet; //if singlesig if (strategyBase is DirectDerivationStrategy) @@ -463,7 +463,7 @@ public async Task TrackAndScanWallet(Wallet wallet){ } else if (strategyBase is P2WSHDerivationStrategy p2WshDerivationStrategy && p2WshDerivationStrategy.Inner is MultisigDerivationStrategy multisigDerivationStrategy) { - + wallet = new Wallet { Id = 0, @@ -486,9 +486,9 @@ public async Task TrackAndScanWallet(Wallet wallet){ { _logger.LogError("Invalid output descriptor"); return (false, "Invalid output descriptor"); - + } - + //Persist wallet var addResult = await AddAsync(wallet); if (addResult.Item1 == false) @@ -496,7 +496,7 @@ public async Task TrackAndScanWallet(Wallet wallet){ _logger.LogError("Error while importing wallet from output descriptor: {Error}", addResult.Item2); return (false, addResult.Item2); } - + //Track wallet var derivationStrategyBase = wallet.GetDerivationStrategy(); if (derivationStrategyBase == null) diff --git a/test/NodeGuard.Tests/Data/Repositories/WalletRepositoryTests.cs b/test/NodeGuard.Tests/Data/Repositories/WalletRepositoryTests.cs index e31d9266..478dc0a4 100644 --- a/test/NodeGuard.Tests/Data/Repositories/WalletRepositoryTests.cs +++ b/test/NodeGuard.Tests/Data/Repositories/WalletRepositoryTests.cs @@ -96,6 +96,7 @@ public async Task GetNextSubderivationPath_ReturnsNext() Name = "TestWallet", IsFinalised = true, IsHotWallet = true, + InternalWalletMasterFingerprint = "abcd", InternalWalletSubDerivationPath = "0" }); context.SaveChanges(); @@ -120,6 +121,7 @@ public async Task GetNextSubderivationPath_DoesntReturnNotFinalisedWallet() Name = "TestWallet", IsFinalised = true, IsHotWallet = true, + InternalWalletMasterFingerprint = "abcd", InternalWalletSubDerivationPath = "0" }); context.Wallets.Add(new Wallet() @@ -127,6 +129,7 @@ public async Task GetNextSubderivationPath_DoesntReturnNotFinalisedWallet() Name = "NotFinalised", IsFinalised = false, IsHotWallet = true, + InternalWalletMasterFingerprint = "abcd", InternalWalletSubDerivationPath = "1" }); context.SaveChanges(); @@ -152,6 +155,7 @@ public async Task GetNextSubderivationPath_ReturnsSubderivedWallet() IsFinalised = true, IsHotWallet = true, IsCompromised = true, + InternalWalletMasterFingerprint = "abcd", InternalWalletSubDerivationPath = "0" }); context.Wallets.Add(new Wallet() @@ -161,6 +165,7 @@ public async Task GetNextSubderivationPath_ReturnsSubderivedWallet() IsHotWallet = true, IsBIP39Imported = true, IsCompromised = true, + InternalWalletMasterFingerprint = "abcd", InternalWalletSubDerivationPath = null }); context.SaveChanges(); @@ -169,7 +174,7 @@ public async Task GetNextSubderivationPath_ReturnsSubderivedWallet() var result = await walletRepository.GetNextSubderivationPath(); result.Should().Be("1"); } - + private WalletRepository SetupTestClassForImportBIP39Wallet() { var keyRepositoryMock = new Mock(); @@ -198,7 +203,7 @@ private WalletRepository SetupTestClassForImportBIP39Wallet() return new WalletRepository(new Repository(new Mock>().Object), loggerMock.Object, setupDbContextFactory.Object, internalWalletRepositoryMock.Object, keyRepositoryMock.Object, nbXplorerServiceMock.Object); } - + [Fact] public async Task ImportBIP39Wallet_WhenValidInput_ShouldReturnSuccess() { @@ -206,7 +211,7 @@ public async Task ImportBIP39Wallet_WhenValidInput_ShouldReturnSuccess() var seedphrase = "social mango annual basic work brain economy one safe physical junk other toy valid load cook napkin maple runway island oil fan legend stem"; var derivationPath = "m/84'/1'/0'"; var userId = "testUser"; - + var testClass = SetupTestClassForImportBIP39Wallet(); // Act @@ -217,7 +222,7 @@ public async Task ImportBIP39Wallet_WhenValidInput_ShouldReturnSuccess() errorMessage.Should().BeNull(); } - + [Fact] public async Task ImportBIP39Wallet_WhenSeedPhraseIsEmpty_ShouldReturnError() { @@ -235,7 +240,7 @@ public async Task ImportBIP39Wallet_WhenSeedPhraseIsEmpty_ShouldReturnError() result.Should().BeFalse(); errorMessage.Should().Be("Seedphrase is empty"); } - + [Fact] public async Task ImportBIP39Wallet_WhenDerivationPathIsEmpty_ShouldReturnError() { @@ -253,7 +258,7 @@ public async Task ImportBIP39Wallet_WhenDerivationPathIsEmpty_ShouldReturnError( result.Should().BeFalse(); errorMessage.Should().Be("Derivation path is empty"); } - + [Fact] public async Task ImportBIP39Wallet_WhenSeedPhraseIsInvalid_ShouldReturnError() {