From c12feff9125d8824aab8007ca7fa03fd7aee75e6 Mon Sep 17 00:00:00 2001 From: Francois de la Rouviere Date: Mon, 25 Jan 2021 08:19:05 +0000 Subject: [PATCH 1/4] Update WalletService.cs --- .../Services/WalletService.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Stratis.Bitcoin.Features.Wallet/Services/WalletService.cs b/src/Stratis.Bitcoin.Features.Wallet/Services/WalletService.cs index 375b0bc328..709007443b 100644 --- a/src/Stratis.Bitcoin.Features.Wallet/Services/WalletService.cs +++ b/src/Stratis.Bitcoin.Features.Wallet/Services/WalletService.cs @@ -186,8 +186,7 @@ public async Task GetBalance( }, cancellationToken); } - public async Task GetHistory(WalletHistoryRequest request, - CancellationToken cancellationToken) + public async Task GetHistory(WalletHistoryRequest request, CancellationToken cancellationToken) { return await Task.Run(() => { @@ -230,8 +229,7 @@ public async Task GetHistory(WalletHistoryRequest request, // Represents a sublist of transactions associated with receive addresses + a sublist of already spent transactions associated with change addresses. // In effect, we filter out 'change' transactions that are not spent, as we don't want to show these in the history. - foreach (FlatHistory item in items.Where(t => - !t.Address.IsChangeAddress() || (t.Address.IsChangeAddress() && t.Transaction.IsSpent()))) + foreach (FlatHistory item in items.Where(t => !t.Address.IsChangeAddress() || (t.Address.IsChangeAddress() && t.Transaction.IsSpent()))) { // Count only unique transactions and limit it to MaxHistoryItemsPerAccount. int processedTransactions = uniqueProcessedTxIds.Count; From 78104dc2ff8acaea429166c4471e3856ea0f1d0c Mon Sep 17 00:00:00 2001 From: Francois de la Rouviere Date: Mon, 25 Jan 2021 08:51:06 +0000 Subject: [PATCH 2/4] Add Filter --- .../SmartContractWalletControllerTest.cs | 10 ++--- .../Wallet/SmartContractWalletController.cs | 2 +- .../WalletControllerTest.cs | 20 +++++----- .../Interfaces/IWalletManager.cs | 8 ++-- .../Services/WalletService.cs | 5 +-- .../WalletManager.cs | 37 +++++++++++-------- 6 files changed, 44 insertions(+), 38 deletions(-) diff --git a/src/Stratis.Bitcoin.Features.SmartContracts.Tests/Controllers/SmartContractWalletControllerTest.cs b/src/Stratis.Bitcoin.Features.SmartContracts.Tests/Controllers/SmartContractWalletControllerTest.cs index 68eaf50374..b18dd2e865 100644 --- a/src/Stratis.Bitcoin.Features.SmartContracts.Tests/Controllers/SmartContractWalletControllerTest.cs +++ b/src/Stratis.Bitcoin.Features.SmartContracts.Tests/Controllers/SmartContractWalletControllerTest.cs @@ -86,13 +86,13 @@ public void GetHistoryWithValidModelWithoutTransactionSpendingDetailsReturnsWall List flat = addresses.SelectMany(s => s.Transactions.Select(t => new FlatHistory { Address = s, Transaction = t })).ToList(); var accountsHistory = new List { new AccountHistory { History = flat, Account = account } }; - this.walletManager.Setup(w => w.GetHistory(walletName, It.IsAny())).Returns(accountsHistory); + this.walletManager.Setup(w => w.GetHistory(walletName, It.IsAny(), null)).Returns(accountsHistory); this.walletManager.Setup(w => w.GetWallet(walletName)).Returns(wallet); this.walletManager.Setup(w => w.GetAccounts(walletName)).Returns(new List { account }); var receipt = new Receipt(null, 12345, new Log[0], null, null, null, uint160.Zero, true, null, null, 2, 100000); this.receiptRepository.Setup(x => x.RetrieveMany(It.IsAny>())) - .Returns(new List {receipt}); + .Returns(new List { receipt }); this.callDataSerializer.Setup(x => x.Deserialize(It.IsAny())) .Returns(Result.Ok(new ContractTxData(0, 0, (Stratis.SmartContracts.RuntimeObserver.Gas)0, new uint160(0), null, null))); @@ -151,12 +151,12 @@ public void GetHistoryWithValidModelWithSkipAndTakeReturnsWalletHistoryModel() for (int i = 0; i < totalHistoryLength; i++) { - TransactionData createTransaction = WalletTestsHelpers.CreateTransaction(new uint256((ulong) i), new Money(500000), 100 + i); + TransactionData createTransaction = WalletTestsHelpers.CreateTransaction(new uint256((ulong)i), new Money(500000), 100 + i); createTransaction.SpendingDetails = new SpendingDetails { BlockHeight = 100 + i, CreationTime = DateTimeOffset.Now, - TransactionId = new uint256((ulong) i), + TransactionId = new uint256((ulong)i), Payments = new List { new PaymentDetails @@ -180,7 +180,7 @@ public void GetHistoryWithValidModelWithSkipAndTakeReturnsWalletHistoryModel() List flat = addresses.SelectMany(s => s.Transactions.Select(t => new FlatHistory { Address = s, Transaction = t })).ToList(); var accountsHistory = new List { new AccountHistory { History = flat, Account = account } }; - this.walletManager.Setup(w => w.GetHistory(walletName, It.IsAny())).Returns(accountsHistory); + this.walletManager.Setup(w => w.GetHistory(walletName, It.IsAny(), null)).Returns(accountsHistory); this.walletManager.Setup(w => w.GetWallet(walletName)).Returns(wallet); this.walletManager.Setup(w => w.GetAccounts(walletName)).Returns(new List { account }); diff --git a/src/Stratis.Bitcoin.Features.SmartContracts/Wallet/SmartContractWalletController.cs b/src/Stratis.Bitcoin.Features.SmartContracts/Wallet/SmartContractWalletController.cs index 3459a75c4c..a104f8a1bf 100644 --- a/src/Stratis.Bitcoin.Features.SmartContracts/Wallet/SmartContractWalletController.cs +++ b/src/Stratis.Bitcoin.Features.SmartContracts/Wallet/SmartContractWalletController.cs @@ -183,7 +183,7 @@ public IActionResult GetHistory(GetHistoryRequest request) HdAccount account = this.walletManager.GetAccounts(request.WalletName).First(); // Get a list of all the transactions found in an account (or in a wallet if no account is specified), with the addresses associated with them. - IEnumerable accountsHistory = this.walletManager.GetHistory(request.WalletName, account.Name); + IEnumerable accountsHistory = this.walletManager.GetHistory(request.WalletName, account.Name, null); // Wallet manager returns only 1 when an account name is specified. AccountHistory accountHistory = accountsHistory.First(); diff --git a/src/Stratis.Bitcoin.Features.Wallet.Tests/WalletControllerTest.cs b/src/Stratis.Bitcoin.Features.Wallet.Tests/WalletControllerTest.cs index a9fb0c05cb..4d23b4e1c6 100644 --- a/src/Stratis.Bitcoin.Features.Wallet.Tests/WalletControllerTest.cs +++ b/src/Stratis.Bitcoin.Features.Wallet.Tests/WalletControllerTest.cs @@ -405,7 +405,8 @@ public async Task RecoverWalletWithFileNotFoundExceptionReturnsNotFound() [Fact] public async Task RecoverWalletWithExceptionReturnsBadRequest() { - var mockWalletManager = this.ConfigureMock(mock => { + var mockWalletManager = this.ConfigureMock(mock => + { mock.Setup(w => w.RecoverWallet(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), null, null)) .Throws(new FormatException("Formatting failed.")); @@ -768,7 +769,7 @@ public async Task GetHistoryWithoutAddressesReturnsEmptyModel() { string walletName = "myWallet"; var mockWalletManager = this.ConfigureMock(mock => - mock.Setup(w => w.GetHistory(walletName, WalletManager.DefaultAccount)).Returns( + mock.Setup(w => w.GetHistory(walletName, WalletManager.DefaultAccount, null)).Returns( new List { new AccountHistory @@ -815,7 +816,7 @@ public async Task GetHistoryWithValidModelWithoutTransactionSpendingDetailsRetur var accountsHistory = new List { new AccountHistory { History = flat, Account = account } }; var mockWalletManager = this.ConfigureMock(mock => - mock.Setup(w => w.GetHistory(walletName, WalletManager.DefaultAccount)) + mock.Setup(w => w.GetHistory(walletName, WalletManager.DefaultAccount, null)) .Returns(accountsHistory)); mockWalletManager.Setup(w => w.GetWallet(walletName)).Returns(wallet); @@ -891,7 +892,7 @@ public async Task GetHistoryWithCoinStakeWithMultipleInputs() var accountsHistory = new List { new AccountHistory { History = flat, Account = account } }; var mockWalletManager = this.ConfigureMock(); - mockWalletManager.Setup(w => w.GetHistory(walletName, WalletManager.DefaultAccount)) + mockWalletManager.Setup(w => w.GetHistory(walletName, WalletManager.DefaultAccount, null)) .Returns(accountsHistory); mockWalletManager.Setup(w => w.GetWallet(walletName)).Returns(wallet); @@ -957,7 +958,7 @@ public async Task GetHistoryWithValidModelWithTransactionSpendingDetailsReturnsW var accountsHistory = new List { new AccountHistory { History = flat, Account = account } }; var mockWalletManager = this.ConfigureMock(mock => - mock.Setup(w => w.GetHistory(walletName, WalletManager.DefaultAccount)) + mock.Setup(w => w.GetHistory(walletName, WalletManager.DefaultAccount, null)) .Returns(accountsHistory)); mockWalletManager.Setup(w => w.GetWallet(walletName)).Returns(wallet); @@ -1037,7 +1038,7 @@ public async Task GetHistoryWithValidModelWithFeeBelowZeroSetsFeeToZero() var accountsHistory = new List { new AccountHistory { History = flat, Account = account } }; var mockWalletManager = this.ConfigureMock(mock => - mock.Setup(w => w.GetHistory(walletName, WalletManager.DefaultAccount)) + mock.Setup(w => w.GetHistory(walletName, WalletManager.DefaultAccount, null)) .Returns(accountsHistory)); mockWalletManager.Setup(w => w.GetWallet(walletName)).Returns(wallet); @@ -1140,7 +1141,7 @@ public async Task GetHistoryWithDuplicateSpentTransactionsSelectsDistinctsSpentT var mockWalletManager = this.ConfigureMock(mock => mock.Setup(w => w.GetWallet(walletName)).Returns(wallet)); - mockWalletManager.Setup(w => w.GetHistory(walletName, WalletManager.DefaultAccount)) + mockWalletManager.Setup(w => w.GetHistory(walletName, WalletManager.DefaultAccount, null)) .Returns(accountsHistory); var controller = this.GetWalletController(); @@ -1177,7 +1178,7 @@ public async Task GetHistoryWithExceptionReturnsBadRequest() { string walletName = "myWallet"; var mockWalletManager = this.ConfigureMock(mock => - mock.Setup(w => w.GetHistory("myWallet", WalletManager.DefaultAccount)) + mock.Setup(w => w.GetHistory("myWallet", WalletManager.DefaultAccount, null)) .Throws(new InvalidOperationException("Issue retrieving wallets."))); mockWalletManager.Setup(w => w.GetWallet(walletName)).Returns(new Wallet()); @@ -1254,8 +1255,7 @@ public async Task GetHistoryWithChangeAddressesShouldIncludeSpentChangeAddesses( var mockWalletManager = this.ConfigureMock(); var accountsHistory = new List { new AccountHistory { History = flat, Account = account } }; - mockWalletManager.Setup(w => - w.GetHistory(walletName, WalletManager.DefaultAccount)).Returns(accountsHistory); + mockWalletManager.Setup(w => w.GetHistory(walletName, WalletManager.DefaultAccount, null)).Returns(accountsHistory); mockWalletManager.Setup(w => w.GetWallet(walletName)).Returns(wallet); var controller = this.GetWalletController(); diff --git a/src/Stratis.Bitcoin.Features.Wallet/Interfaces/IWalletManager.cs b/src/Stratis.Bitcoin.Features.Wallet/Interfaces/IWalletManager.cs index b17bc5ab54..79ebd7ccad 100644 --- a/src/Stratis.Bitcoin.Features.Wallet/Interfaces/IWalletManager.cs +++ b/src/Stratis.Bitcoin.Features.Wallet/Interfaces/IWalletManager.cs @@ -156,7 +156,7 @@ public interface IWalletManager /// The extended public key. /// The account number. /// The date and time this wallet was created. - /// + /// The recovered wallet. Wallet RecoverWallet(string name, ExtPubKey extPubKey, int accountIndex, DateTime creationTime, ChainedHeader lastBlockSynced = null); /// @@ -244,8 +244,9 @@ public interface IWalletManager /// /// The wallet name. /// The account name. + /// For now this can only be a transaction Id. /// Collection of address history and transaction pairs. - IEnumerable GetHistory(string walletName, string accountName = null); + IEnumerable GetHistory(string walletName, string accountName = null, string searchQuery = null); /// /// Gets the history of transactions contained in an account. @@ -256,8 +257,9 @@ public interface IWalletManager /// Previous OutputTxTime, used for pagination /// Previous prevOutputIndex, used for pagination /// Number of records to Take + /// For now this can only be a transaction Id. /// Collection of address history and transaction pairs. - IEnumerable GetHistory(string walletName, string accountName = null, long? prevOutputTxTime = null, int? prevOutputIndex = null, int? take = int.MaxValue); + IEnumerable GetHistory(string walletName, string accountName = null, long? prevOutputTxTime = null, int? prevOutputIndex = null, int? take = int.MaxValue, string searchQuery = null); /// /// Gets the history of the transactions in addresses contained in this account. diff --git a/src/Stratis.Bitcoin.Features.Wallet/Services/WalletService.cs b/src/Stratis.Bitcoin.Features.Wallet/Services/WalletService.cs index 709007443b..c4921f211d 100644 --- a/src/Stratis.Bitcoin.Features.Wallet/Services/WalletService.cs +++ b/src/Stratis.Bitcoin.Features.Wallet/Services/WalletService.cs @@ -194,9 +194,8 @@ public async Task GetHistory(WalletHistoryRequest request, C // Get a list of all the transactions found in an account (or in a wallet if no account is specified), with the addresses associated with them. IEnumerable accountsHistory = request.Take == null - ? this.walletManager.GetHistory(request.WalletName, request.AccountName) - : this.walletManager.GetHistory(request.WalletName, request.AccountName, request.PrevOutputTxTime, - request.PrevOutputIndex, request.Take); + ? this.walletManager.GetHistory(request.WalletName, request.AccountName, request.SearchQuery) + : this.walletManager.GetHistory(request.WalletName, request.AccountName, request.PrevOutputTxTime, request.PrevOutputIndex, request.Take); foreach (AccountHistory accountHistory in accountsHistory) { diff --git a/src/Stratis.Bitcoin.Features.Wallet/WalletManager.cs b/src/Stratis.Bitcoin.Features.Wallet/WalletManager.cs index 2d1105161d..853dc01854 100644 --- a/src/Stratis.Bitcoin.Features.Wallet/WalletManager.cs +++ b/src/Stratis.Bitcoin.Features.Wallet/WalletManager.cs @@ -870,13 +870,13 @@ public IEnumerable GetNewAddresses(WalletAccountReference accountRefe return this.WalletRepository.GetUsedAddresses(accountReference, isChange); } - public IEnumerable GetHistory(string walletName, string accountName = null) + public IEnumerable GetHistory(string walletName, string accountName = null, string searchQuery = null) { - return this.GetHistory(walletName, accountName, null, null, int.MaxValue); + return this.GetHistory(walletName, accountName, null, null, int.MaxValue, searchQuery); } - + /// - public IEnumerable GetHistory(string walletName, string accountName, long? prevOutputTxTime, int? prevOutputIndex, int? take = int.MaxValue) + public IEnumerable GetHistory(string walletName, string accountName, long? prevOutputTxTime, int? prevOutputIndex, int? take = int.MaxValue, string searchQuery = null) { Guard.NotEmpty(walletName, nameof(walletName)); @@ -903,7 +903,7 @@ public IEnumerable GetHistory(string walletName, string accountN foreach (HdAccount account in accounts) { - accountsHistory.Add(this.GetHistoryForAccount(account, prevOutputTxTime, prevOutputIndex, take.GetValueOrDefault())); + accountsHistory.Add(this.GetHistoryForAccount(account, prevOutputTxTime, prevOutputIndex, take.GetValueOrDefault(), searchQuery)); } } @@ -915,8 +915,8 @@ public AccountHistory GetHistory(HdAccount account) { return this.GetHistoryForAccount(account, null, null, int.MaxValue); } - - protected AccountHistory GetHistoryForAccount(HdAccount account, long? prevOutputTxTime = null, int? prevOutputIndex = null, int take = int.MaxValue) + + protected AccountHistory GetHistoryForAccount(HdAccount account, long? prevOutputTxTime = null, int? prevOutputIndex = null, int take = int.MaxValue, string searchQuery = null) { Guard.NotNull(account, nameof(account)); FlatHistory[] items; @@ -926,16 +926,21 @@ protected AccountHistory GetHistoryForAccount(HdAccount account, long? prevOutpu // Get transactions contained in the account. var query = account.GetCombinedAddresses().Where(a => a.Transactions.Any()); - if (account.IsNormalAccount()) - { - // When the account is a normal one, we want to filter out all cold stake UTXOs. - items = query.SelectMany(s => s.Transactions.Where(t => t.IsColdCoinStake == null || t.IsColdCoinStake == false).Select(t => new FlatHistory { Address = s, Transaction = t })).ToArray(); - } + if (uint256.TryParse(searchQuery, out uint256 parsedTxId)) + items = query.SelectMany(s => s.Transactions.Where(t => t.Id == parsedTxId).Select(t => new FlatHistory { Address = s, Transaction = t })).ToArray(); else { - items = account.GetCombinedAddresses() - .Where(a => a.Transactions.Any()) - .SelectMany(s => s.Transactions.Select(t => new FlatHistory { Address = s, Transaction = t })).ToArray(); + if (account.IsNormalAccount()) + { + // When the account is a normal one, we want to filter out all cold stake UTXOs. + items = query.SelectMany(s => s.Transactions.Where(t => t.IsColdCoinStake == null || t.IsColdCoinStake == false).Select(t => new FlatHistory { Address = s, Transaction = t })).ToArray(); + } + else + { + items = account.GetCombinedAddresses() + .Where(a => a.Transactions.Any()) + .SelectMany(s => s.Transactions.Select(t => new FlatHistory { Address = s, Transaction = t })).ToArray(); + } } } @@ -1207,7 +1212,7 @@ public void ProcessBlocks(Func Date: Mon, 25 Jan 2021 09:01:55 +0000 Subject: [PATCH 3/4] Fix Test --- src/Stratis.Bitcoin.Features.Wallet/WalletManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Stratis.Bitcoin.Features.Wallet/WalletManager.cs b/src/Stratis.Bitcoin.Features.Wallet/WalletManager.cs index 853dc01854..1e89280ae4 100644 --- a/src/Stratis.Bitcoin.Features.Wallet/WalletManager.cs +++ b/src/Stratis.Bitcoin.Features.Wallet/WalletManager.cs @@ -926,7 +926,7 @@ protected AccountHistory GetHistoryForAccount(HdAccount account, long? prevOutpu // Get transactions contained in the account. var query = account.GetCombinedAddresses().Where(a => a.Transactions.Any()); - if (uint256.TryParse(searchQuery, out uint256 parsedTxId)) + if (searchQuery != null && uint256.TryParse(searchQuery, out uint256 parsedTxId)) items = query.SelectMany(s => s.Transactions.Where(t => t.Id == parsedTxId).Select(t => new FlatHistory { Address = s, Transaction = t })).ToArray(); else { From 668c4243c15da2e9c5c7ee5ba4f11fb4eb65dc7e Mon Sep 17 00:00:00 2001 From: Francois de la Rouviere Date: Mon, 25 Jan 2021 15:08:33 +0000 Subject: [PATCH 4/4] Perform check for cold staking txs --- .../WalletManager.cs | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/Stratis.Bitcoin.Features.Wallet/WalletManager.cs b/src/Stratis.Bitcoin.Features.Wallet/WalletManager.cs index 1e89280ae4..0df2478631 100644 --- a/src/Stratis.Bitcoin.Features.Wallet/WalletManager.cs +++ b/src/Stratis.Bitcoin.Features.Wallet/WalletManager.cs @@ -926,21 +926,19 @@ protected AccountHistory GetHistoryForAccount(HdAccount account, long? prevOutpu // Get transactions contained in the account. var query = account.GetCombinedAddresses().Where(a => a.Transactions.Any()); - if (searchQuery != null && uint256.TryParse(searchQuery, out uint256 parsedTxId)) - items = query.SelectMany(s => s.Transactions.Where(t => t.Id == parsedTxId).Select(t => new FlatHistory { Address = s, Transaction = t })).ToArray(); - else + // When the account is a normal one, we want to filter out all cold stake UTXOs. + if (account.IsNormalAccount()) { - if (account.IsNormalAccount()) - { - // When the account is a normal one, we want to filter out all cold stake UTXOs. - items = query.SelectMany(s => s.Transactions.Where(t => t.IsColdCoinStake == null || t.IsColdCoinStake == false).Select(t => new FlatHistory { Address = s, Transaction = t })).ToArray(); - } + if (searchQuery != null && uint256.TryParse(searchQuery, out uint256 parsedTxId)) + items = query.SelectMany(s => s.Transactions.Where(t => (t.IsColdCoinStake == null || t.IsColdCoinStake == false) && t.Id == parsedTxId).Select(t => new FlatHistory { Address = s, Transaction = t })).ToArray(); else - { - items = account.GetCombinedAddresses() - .Where(a => a.Transactions.Any()) - .SelectMany(s => s.Transactions.Select(t => new FlatHistory { Address = s, Transaction = t })).ToArray(); - } + items = query.SelectMany(s => s.Transactions.Where(t => t.IsColdCoinStake == null || t.IsColdCoinStake == false).Select(t => new FlatHistory { Address = s, Transaction = t })).ToArray(); + } + else + { + items = account.GetCombinedAddresses() + .Where(a => a.Transactions.Any()) + .SelectMany(s => s.Transactions.Select(t => new FlatHistory { Address = s, Transaction = t })).ToArray(); } }