Prepare wallet load speadup, fix unconfirmed serialization (again)
MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/SendTabViewModel.cs
WalletWasabi.Gui/Controls/WalletExplorer/SendTabViewModel.cs
@@ -376,7 +376,7 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
}
MainWindowViewModel.Instance.StatusBar.TryAddStatus(StatusBarStatus.BroadcastingTransaction);
- await Task.Run(async () => await Global.WalletService.SendTransactionAsync(signedTransaction));
+ await Global.WalletService.SendTransactionAsync(signedTransaction);
TryResetInputsOnSuccess("Transaction is successfully sent!");
}

MODIFY
WalletWasabi/Services/WalletService.cs
WalletWasabi/Services/WalletService.cs
@@ -264,14 +264,43 @@ namespace WalletWasabi.Services
using (await HandleFiltersLock.LockAsync())
{
+ SmartTransaction[] unconfirmedTransactions = null;
+ SmartTransaction[] confirmedTransactions = null;
+
+ if (File.Exists(TransactionsFilePath))
+ {
+ try
+ {
+ IEnumerable<SmartTransaction> transactions = null;
+ string jsonString = File.ReadAllText(TransactionsFilePath, Encoding.UTF8);
+ transactions = JsonConvert.DeserializeObject<IEnumerable<SmartTransaction>>(jsonString)?
+ .OrderByBlockchain();
+
+ confirmedTransactions = transactions?
+ .Where(x => x.Confirmed)?
+ .ToArray() ?? new SmartTransaction[0];
+
+ unconfirmedTransactions = transactions?
+ .Where(x => !x.Confirmed)?
+ .ToArray() ?? new SmartTransaction[0];
+ }
+ catch (Exception ex)
+ {
+ Logger.LogWarning<WalletService>(ex);
+ Logger.LogWarning<WalletService>($"Transaction cache got corrupted. Deleting {TransactionsFilePath}.");
+ File.Delete(TransactionsFilePath);
+ }
+ }
+
// Go through the keymanager's index.
KeyManager.AssertNetworkOrClearBlockstate(Network);
Height bestKeyManagerHeight = KeyManager.GetBestHeight();
- foreach (var blockstate in KeyManager.GetTransactionIndex())
+ foreach (BlockState blockstate in KeyManager.GetTransactionIndex())
{
+ var relevantTransactions = confirmedTransactions.Where(x => x.BlockHash == blockstate.BlockHash).ToArray();
var block = await GetOrDownloadBlockAsync(blockstate.BlockHash, cancel);
- await ProcessBlockAsync(blockstate.BlockHeight, block, blockstate.TransactionIndices);
+ await ProcessBlockAsync(blockstate.BlockHeight, block, blockstate.TransactionIndices, relevantTransactions);
}
// Go through the filters and que to download the matches.
@@ -284,27 +313,9 @@ namespace WalletWasabi.Services
}, new Height(bestKeyManagerHeight.Value + 1));
// Load in dummy mempool
- if (File.Exists(TransactionsFilePath))
- {
- try
- {
- SmartTransaction[] transactions = null;
try
{
- string jsonString = File.ReadAllText(TransactionsFilePath, Encoding.UTF8);
- transactions = JsonConvert.DeserializeObject<IEnumerable<SmartTransaction>>(jsonString)?
- .Where(x => !x.Confirmed)? // Only unconfirmed ones.
- .OrderByBlockchain()?
- .ToArray();
- }
- catch (Exception ex)
- {
- Logger.LogWarning<WalletService>(ex);
- Logger.LogWarning<WalletService>($"Transaction cache got corrupted. Deleting {TransactionsFilePath}.");
- File.Delete(TransactionsFilePath);
- }
-
- if (transactions != null && transactions.Any())
+ if (unconfirmedTransactions != null && unconfirmedTransactions.Any())
{
try
{
@@ -316,7 +327,7 @@ namespace WalletWasabi.Services
var mempoolHashes = await client.GetMempoolHashesAsync(compactness);
var cnt = 0;
- foreach (var tx in transactions)
+ foreach (var tx in unconfirmedTransactions)
{
if (mempoolHashes.Contains(tx.GetHash().ToString().Substring(0, compactness)))
{
@@ -329,9 +340,7 @@ namespace WalletWasabi.Services
}
}
- UnconfirmedTransactionsInitialized = true;
-
- if (cnt != transactions.Count())
+ if (cnt != unconfirmedTransactions.Count())
{
SerializeTransactionCache();
}
@@ -340,7 +349,7 @@ namespace WalletWasabi.Services
catch
{
// When there's a connection failure don't clean the transactions, add it to processing.
- foreach (var tx in transactions)
+ foreach (var tx in unconfirmedTransactions)
{
tx.SetHeight(Height.MemPool);
await ProcessTransactionAsync(tx);
@@ -355,6 +364,9 @@ namespace WalletWasabi.Services
{
Logger.LogWarning<WalletService>(ex);
}
+ finally
+ {
+ UnconfirmedTransactionsInitialized = true;
}
}
Coins.CollectionChanged += Coins_CollectionChanged;
@@ -476,7 +488,7 @@ namespace WalletWasabi.Services
return clusters;
}
- private async Task<bool> ProcessBlockAsync(Height height, Block block, IEnumerable<int> filterByTxIds = null)
+ private async Task<bool> ProcessBlockAsync(Height height, Block block, IEnumerable<int> filterByTxIds = null, IEnumerable<SmartTransaction> skeletonBlock = null)
{
var ret = false;
using (await TransactionProcessingLock.LockAsync())
@@ -508,8 +520,8 @@ namespace WalletWasabi.Services
{
foreach (var i in filterByTxIds.OrderBy(x => x))
{
- Transaction tx = block.Transactions[i];
- if (await ProcessTransactionAsync(new SmartTransaction(tx, height, block.GetHash(), i)))
+ var tx = skeletonBlock?.FirstOrDefault(x => x.BlockIndex == i) ?? new SmartTransaction(block.Transactions[i], height, block.GetHash(), i);
+ if (await ProcessTransactionAsync(tx))
{
ret = true;
}
@@ -720,8 +732,6 @@ namespace WalletWasabi.Services
private set => _localBitcoinCoreNode = value;
}
- public bool UnconfirmedTransactionsInitialized { get; private set; }
-
/// <exception cref="OperationCanceledException"></exception>
public async Task<Block> GetOrDownloadBlockAsync(uint256 hash, CancellationToken cancel)
{
@@ -1588,6 +1598,8 @@ namespace WalletWasabi.Services
}
}
+ public bool UnconfirmedTransactionsInitialized { get; private set; } = false;
+
private void SerializeTransactionCache()
{
if (!UnconfirmedTransactionsInitialized) // If unconfirmed ones are not yet initialized, then don't serialize because unconfirmed are going to be lost.

Prepare wallet load speadup, fix unconfirmed serialization (again)