Implement cancelling initialization for BitcoinStore
MODIFY
WalletWasabi.Gui/Global.cs
WalletWasabi.Gui/Global.cs
@@ -127,7 +127,6 @@ namespace WalletWasabi.Gui
public async Task InitializeNoWalletAsync(TerminateService terminateService)
{
InitializationStarted = true;
- AddressManager = null;
var cancel = StoppingCts.Token;
try
@@ -141,7 +140,7 @@ namespace WalletWasabi.Gui
SizeLimit = 1_000,
ExpirationScanFrequency = TimeSpan.FromSeconds(30)
});
- var bstoreInitTask = BitcoinStore.InitializeAsync();
+ var bstoreInitTask = BitcoinStore.InitializeAsync(cancel);
cancel.ThrowIfCancellationRequested();

MODIFY
WalletWasabi/Blockchain/Transactions/AllTransactionStore.cs
WalletWasabi/Blockchain/Transactions/AllTransactionStore.cs
@@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
+using System.Threading;
using System.Threading.Tasks;
using WalletWasabi.Blockchain.Analysis.Clustering;
using WalletWasabi.Helpers;
@@ -34,7 +35,7 @@ namespace WalletWasabi.Blockchain.Transactions
public TransactionStore ConfirmedStore { get; }
private object Lock { get; } = new object();
- public async Task InitializeAsync(bool ensureBackwardsCompatibility = true)
+ public async Task InitializeAsync(CancellationToken cancel, bool ensureBackwardsCompatibility = true)
{
using (BenchmarkLogger.Measure())
{
@@ -43,8 +44,8 @@ namespace WalletWasabi.Blockchain.Transactions
var initTasks = new[]
{
- MempoolStore.InitializeAsync(mempoolWorkFolder, Network, $"{nameof(MempoolStore)}.{nameof(MempoolStore.InitializeAsync)}"),
- ConfirmedStore.InitializeAsync(confirmedWorkFolder, Network, $"{nameof(ConfirmedStore)}.{nameof(ConfirmedStore.InitializeAsync)}")
+ MempoolStore.InitializeAsync(mempoolWorkFolder, Network, $"{nameof(MempoolStore)}.{nameof(MempoolStore.InitializeAsync)}", cancel),
+ ConfirmedStore.InitializeAsync(confirmedWorkFolder, Network, $"{nameof(ConfirmedStore)}.{nameof(ConfirmedStore.InitializeAsync)}", cancel)
};
await Task.WhenAll(initTasks).ConfigureAwait(false);
@@ -52,6 +53,7 @@ namespace WalletWasabi.Blockchain.Transactions
if (ensureBackwardsCompatibility)
{
+ cancel.ThrowIfCancellationRequested();
EnsureBackwardsCompatibility();
}
}

MODIFY
WalletWasabi/Blockchain/Transactions/TransactionStore.cs
WalletWasabi/Blockchain/Transactions/TransactionStore.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Threading;
using System.Threading.Tasks;
using WalletWasabi.Blockchain.Transactions.Operations;
using WalletWasabi.Helpers;
@@ -28,7 +29,7 @@ namespace WalletWasabi.Blockchain.Transactions
private AbandonedTasks AbandonedTasks { get; } = new AbandonedTasks();
- public async Task InitializeAsync(string workFolderPath, Network network, string operationName)
+ public async Task InitializeAsync(string workFolderPath, Network network, string operationName, CancellationToken cancel)
{
using (BenchmarkLogger.Measure(operationName: operationName))
{
@@ -40,27 +41,31 @@ namespace WalletWasabi.Blockchain.Transactions
// In Transactions.dat every line starts with the tx id, so the first character is the best for digest creation.
TransactionsFileManager = new IoManager(transactionsFilePath);
+ cancel.ThrowIfCancellationRequested();
using (await TransactionsFileAsyncLock.LockAsync().ConfigureAwait(false))
{
IoHelpers.EnsureDirectoryExists(WorkFolderPath);
+ cancel.ThrowIfCancellationRequested();
if (!TransactionsFileManager.Exists())
{
await SerializeAllTransactionsNoLockAsync().ConfigureAwait(false);
+ cancel.ThrowIfCancellationRequested();
}
- await InitializeTransactionsNoLockAsync().ConfigureAwait(false);
+ await InitializeTransactionsNoLockAsync(cancel).ConfigureAwait(false);
}
}
}
- private async Task InitializeTransactionsNoLockAsync()
+ private async Task InitializeTransactionsNoLockAsync(CancellationToken cancel)
{
try
{
IoHelpers.EnsureFileExists(TransactionsFileManager.FilePath);
+ cancel.ThrowIfCancellationRequested();
- var allLines = await TransactionsFileManager.ReadAllLinesAsync().ConfigureAwait(false);
+ var allLines = await TransactionsFileManager.ReadAllLinesAsync(cancel).ConfigureAwait(false);
var allTransactions = allLines
.Select(x => SmartTransaction.FromLine(x, Network))
.OrderByBlockchain();
@@ -85,12 +90,13 @@ namespace WalletWasabi.Blockchain.Transactions
if (added || updated)
{
+ cancel.ThrowIfCancellationRequested();
// Another process worked into the file and appended the same transaction into it.
// In this case we correct the file by serializing the unique set.
await SerializeAllTransactionsNoLockAsync().ConfigureAwait(false);
}
}
- catch
+ catch (Exception ex) when (ex is not OperationCanceledException)
{
// We found a corrupted entry. Stop here.
// Delete the currupted file.

MODIFY
WalletWasabi/Stores/BitcoinStore.cs
WalletWasabi/Stores/BitcoinStore.cs
@@ -43,14 +43,14 @@ namespace WalletWasabi.Stores
/// </summary>
public UntrustedP2pBehavior CreateUntrustedP2pBehavior() => new UntrustedP2pBehavior(MempoolService);
- public async Task InitializeAsync()
+ public async Task InitializeAsync(CancellationToken cancel)
{
using (BenchmarkLogger.Measure())
{
var initTasks = new[]
{
- IndexStore.InitializeAsync(),
- TransactionStore.InitializeAsync()
+ IndexStore.InitializeAsync(cancel),
+ TransactionStore.InitializeAsync(cancel)
};
await Task.WhenAll(initTasks).ConfigureAwait(false);

MODIFY
WalletWasabi/Stores/IndexStore.cs
WalletWasabi/Stores/IndexStore.cs
@@ -72,7 +72,7 @@ namespace WalletWasabi.Stores
/// </summary>
private AsyncLock IndexLock { get; } = new AsyncLock();
- public async Task InitializeAsync()
+ public async Task InitializeAsync(CancellationToken cancel)
{
using (BenchmarkLogger.Measure())
{
@@ -82,6 +82,8 @@ namespace WalletWasabi.Stores
{
IoHelpers.EnsureDirectoryExists(WorkFolderPath);
+ cancel.ThrowIfCancellationRequested();
+
await EnsureBackwardsCompatibilityAsync().ConfigureAwait(false);
if (Network == Network.RegTest)
@@ -89,13 +91,15 @@ namespace WalletWasabi.Stores
MatureIndexFileManager.DeleteMe(); // RegTest is not a global ledger, better to delete it.
ImmatureIndexFileManager.DeleteMe();
}
+ cancel.ThrowIfCancellationRequested();
if (!MatureIndexFileManager.Exists())
{
await MatureIndexFileManager.WriteAllLinesAsync(new[] { StartingFilter.ToLine() }).ConfigureAwait(false);
}
+ cancel.ThrowIfCancellationRequested();
- await InitializeFiltersAsync().ConfigureAwait(false);
+ await InitializeFiltersAsync(cancel).ConfigureAwait(false);
}
}
}
@@ -134,7 +138,7 @@ namespace WalletWasabi.Stores
}
}
- private async Task InitializeFiltersAsync()
+ private async Task InitializeFiltersAsync(CancellationToken cancel)
{
try
{
@@ -148,6 +152,7 @@ namespace WalletWasabi.Stores
while (lineTask is { })
{
line ??= await lineTask.ConfigureAwait(false);
+ cancel.ThrowIfCancellationRequested();
lineTask = sr.EndOfStream ? null : sr.ReadLineAsync();
@@ -158,7 +163,7 @@ namespace WalletWasabi.Stores
}
}
}
- catch
+ catch (Exception ex) when (ex is not OperationCanceledException)
{
// We found a corrupted entry. Stop here.
// Delete the currupted file.
@@ -168,6 +173,7 @@ namespace WalletWasabi.Stores
ImmatureIndexFileManager.DeleteMe();
throw;
}
+ cancel.ThrowIfCancellationRequested();
try
{
@@ -176,10 +182,11 @@ namespace WalletWasabi.Stores
foreach (var line in await ImmatureIndexFileManager.ReadAllLinesAsync().ConfigureAwait(false)) // We can load ImmatureIndexFileManager to the memory, no problem.
{
ProcessLine(line, enqueue: true);
+ cancel.ThrowIfCancellationRequested();
}
}
}
- catch
+ catch (Exception ex) when (ex is not OperationCanceledException)
{
// We found a corrupted entry. Stop here.
// Delete the currupted file.

Implement cancelling initialization for BitcoinStore