Fix warnings in Backend project (take 3)
* Revert "Revert "Fix warnings in Backend project (take 2) (#8100)""
This reverts commit
* fix
MODIFY
WalletWasabi.Backend/Global.cs
WalletWasabi.Backend/Global.cs
@@ -25,75 +25,83 @@ public class Global : IDisposable
{
private bool _disposedValue;
- public Global(string dataDir)
+ public Global(string dataDir, IRPCClient rpcClient, Config config)
{
DataDir = dataDir ?? EnvironmentHelpers.GetDataDir(Path.Combine("WalletWasabi", "Backend"));
+ RpcClient = rpcClient;
+ Config = config;
HostedServices = new();
+ HttpClient = new();
+
+ CoordinatorParameters = new(DataDir);
+ CoinJoinIdStore = CoinJoinIdStore.Create(Path.Combine(DataDir, "CcjCoordinator", $"CoinJoins{RpcClient.Network}.txt"), CoordinatorParameters.CoinJoinIdStoreFilePath);
+
+ // We have to find it, because it's cloned by the node and not perfectly cloned (event handlers cannot be cloned.)
+ P2pNode = new(config.Network, config.GetBitcoinP2pEndPoint(), new(), $"/WasabiCoordinator:{Constants.BackendMajorVersion}/");
+ HostedServices.Register<BlockNotifier>(() => new BlockNotifier(TimeSpan.FromSeconds(7), rpcClient, P2pNode), "Block Notifier");
+
+ // Initialize index building
+ string indexFilePath = Path.Combine(DataDir, "IndexBuilderService", $"Index{RpcClient.Network}.dat");
+ IndexBuilderService = new(RpcClient, HostedServices.Get<BlockNotifier>(), indexFilePath);
}
public string DataDir { get; }
- public IRPCClient? RpcClient { get; private set; }
+ public IRPCClient RpcClient { get; }
- public P2pNode? P2pNode { get; private set; }
+ public P2pNode P2pNode { get; }
public HostedServices HostedServices { get; }
- public IndexBuilderService? IndexBuilderService { get; private set; }
- public HttpClient? HttpClient { get; set; }
+ public IndexBuilderService IndexBuilderService { get; }
+
+ private HttpClient HttpClient { get; }
public Coordinator? Coordinator { get; private set; }
- public Config? Config { get; private set; }
+ public Config Config { get; }
public CoordinatorRoundConfig? RoundConfig { get; private set; }
- public CoinJoinIdStore? CoinJoinIdStore { get; private set; }
+
+ private CoordinatorParameters CoordinatorParameters { get; }
+
+ public CoinJoinIdStore CoinJoinIdStore { get; }
public WabiSabiCoordinator? WabiSabiCoordinator { get; private set; }
- public async Task InitializeAsync(Config config, CoordinatorRoundConfig roundConfig, IRPCClient rpc, CancellationToken cancel)
+ public async Task InitializeAsync(CoordinatorRoundConfig roundConfig, CancellationToken cancel)
{
- Config = Guard.NotNull(nameof(config), config);
RoundConfig = Guard.NotNull(nameof(roundConfig), roundConfig);
- RpcClient = Guard.NotNull(nameof(rpc), rpc);
// Make sure RPC works.
await AssertRpcNodeFullyInitializedAsync(cancel);
// Make sure P2P works.
- await InitializeP2pAsync(config.Network, config.GetBitcoinP2pEndPoint(), cancel);
+ await P2pNode.ConnectAsync(cancel).ConfigureAwait(false);
- var p2pNode = Guard.NotNull(nameof(P2pNode), P2pNode);
- HostedServices.Register<MempoolMirror>(() => new MempoolMirror(TimeSpan.FromSeconds(21), RpcClient, p2pNode), "Full Node Mempool Mirror");
+ HostedServices.Register<MempoolMirror>(() => new MempoolMirror(TimeSpan.FromSeconds(21), RpcClient, P2pNode), "Full Node Mempool Mirror");
- // Initialize index building
- var indexBuilderServiceDir = Path.Combine(DataDir, "IndexBuilderService");
- var indexFilePath = Path.Combine(indexBuilderServiceDir, $"Index{RpcClient.Network}.dat");
var blockNotifier = HostedServices.Get<BlockNotifier>();
- CoordinatorParameters coordinatorParameters = new(DataDir);
-
- CoinJoinIdStore = CoinJoinIdStore.Create(Path.Combine(DataDir, "CcjCoordinator", $"CoinJoins{RpcClient.Network}.txt"), coordinatorParameters.CoinJoinIdStoreFilePath);
- bool shouldBuildCoinVerifier = coordinatorParameters.RuntimeCoordinatorConfig.IsCoinVerifierEnabled || roundConfig.IsCoinVerifierEnabledForWW1;
+ bool shouldBuildCoinVerifier = CoordinatorParameters.RuntimeCoordinatorConfig.IsCoinVerifierEnabled || roundConfig.IsCoinVerifierEnabledForWW1;
CoinVerifier? coinVerifier = null;
if (shouldBuildCoinVerifier)
{
try
{
- if (!Uri.TryCreate(coordinatorParameters.RuntimeCoordinatorConfig.CoinVerifierApiUrl, UriKind.RelativeOrAbsolute, out Uri? url))
+ if (!Uri.TryCreate(CoordinatorParameters.RuntimeCoordinatorConfig.CoinVerifierApiUrl, UriKind.RelativeOrAbsolute, out Uri? url))
{
throw new ArgumentException("Blacklist API URL is invalid in WabiSabiConfig.json.");
}
- if (string.IsNullOrEmpty(coordinatorParameters.RuntimeCoordinatorConfig.CoinVerifierApiAuthToken))
+ if (string.IsNullOrEmpty(CoordinatorParameters.RuntimeCoordinatorConfig.CoinVerifierApiAuthToken))
{
throw new ArgumentException("Blacklist API token was not provided in WabiSabiConfig.json.");
}
- HttpClient = new HttpClient();
HttpClient.BaseAddress = url;
- var coinVerifierApiClient = new CoinVerifierApiClient(coordinatorParameters.RuntimeCoordinatorConfig.CoinVerifierApiAuthToken, rpc.Network, HttpClient);
- var whitelist = await Whitelist.CreateAndLoadFromFileAsync(coordinatorParameters.WhitelistFilePath, cancel).ConfigureAwait(false);
- coinVerifier = new(CoinJoinIdStore, coinVerifierApiClient, whitelist, coordinatorParameters.RuntimeCoordinatorConfig);
+ var coinVerifierApiClient = new CoinVerifierApiClient(CoordinatorParameters.RuntimeCoordinatorConfig.CoinVerifierApiAuthToken, RpcClient.Network, HttpClient);
+ var whitelist = await Whitelist.CreateAndLoadFromFileAsync(CoordinatorParameters.WhitelistFilePath, cancel).ConfigureAwait(false);
+ coinVerifier = new(CoinJoinIdStore, coinVerifierApiClient, whitelist, CoordinatorParameters.RuntimeCoordinatorConfig);
Logger.LogInfo("CoinVerifier created successfully.");
}
catch (Exception exc)
@@ -128,16 +136,15 @@ public class Global : IDisposable
"Config Watcher");
}
- var coinJoinScriptStore = CoinJoinScriptStore.LoadFromFile(coordinatorParameters.CoinJoinScriptStoreFilePath);
+ var coinJoinScriptStore = CoinJoinScriptStore.LoadFromFile(CoordinatorParameters.CoinJoinScriptStoreFilePath);
- WabiSabiCoordinator = new WabiSabiCoordinator(coordinatorParameters, RpcClient, CoinJoinIdStore, coinJoinScriptStore, coordinatorParameters.RuntimeCoordinatorConfig.IsCoinVerifierEnabled ? coinVerifier : null);
+ WabiSabiCoordinator = new WabiSabiCoordinator(CoordinatorParameters, RpcClient, CoinJoinIdStore, coinJoinScriptStore, CoordinatorParameters.RuntimeCoordinatorConfig.IsCoinVerifierEnabled ? coinVerifier : null);
HostedServices.Register<WabiSabiCoordinator>(() => WabiSabiCoordinator, "WabiSabi Coordinator");
HostedServices.Register<RoundBootstrapper>(() => new RoundBootstrapper(TimeSpan.FromMilliseconds(100), Coordinator), "Round Bootstrapper");
await HostedServices.StartAllAsync(cancel);
- IndexBuilderService = new(RpcClient, blockNotifier, indexFilePath);
IndexBuilderService.Synchronize();
Logger.LogInfo($"{nameof(IndexBuilderService)} is successfully initialized and started synchronization.");
}
@@ -147,18 +154,6 @@ public class Global : IDisposable
CoinJoinIdStore!.TryAdd(transaction.GetHash());
}
- private async Task InitializeP2pAsync(Network network, EndPoint endPoint, CancellationToken cancel)
- {
- Guard.NotNull(nameof(network), network);
- Guard.NotNull(nameof(endPoint), endPoint);
- var rpcClient = Guard.NotNull(nameof(RpcClient), RpcClient);
-
- // We have to find it, because it's cloned by the node and not perfectly cloned (event handlers cannot be cloned.)
- P2pNode = new(network, endPoint, new(), $"/WasabiCoordinator:{Constants.BackendMajorVersion}/");
- await P2pNode.ConnectAsync(cancel).ConfigureAwait(false);
- HostedServices.Register<BlockNotifier>(() => new BlockNotifier(TimeSpan.FromSeconds(7), rpcClient, P2pNode), "Block Notifier");
- }
-
private async Task AssertRpcNodeFullyInitializedAsync(CancellationToken cancellationToken)
{
var rpcClient = Guard.NotNull(nameof(RpcClient), RpcClient);
@@ -220,10 +215,7 @@ public class Global : IDisposable
{
if (disposing)
{
- if (HttpClient is { } httpClient)
- {
- httpClient.Dispose();
- }
+ HttpClient.Dispose();
if (Coordinator is { } coordinator)
{

MODIFY
WalletWasabi.Backend/InitConfigStartupTask.cs
WalletWasabi.Backend/InitConfigStartupTask.cs
-using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Caching.Memory;
-using NBitcoin;
using NBitcoin.RPC;
using System.IO;
using System.Threading;
@@ -14,14 +12,12 @@ namespace WalletWasabi.Backend;
public class InitConfigStartupTask : IStartupTask
{
- public InitConfigStartupTask(Global global, IMemoryCache cache)
+ public InitConfigStartupTask(Global global)
{
Global = global;
- Cache = cache;
}
- public Global Global { get; }
- public IMemoryCache Cache { get; }
+ private Global Global { get; }
public async Task ExecuteAsync(CancellationToken cancellationToken)
{
@@ -30,24 +26,13 @@ public class InitConfigStartupTask : IStartupTask
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
- var configFilePath = Path.Combine(Global.DataDir, "Config.json");
- var config = new Config(configFilePath);
- config.LoadOrCreateDefaultFile();
- Logger.LogInfo("Config is successfully initialized.");
var roundConfigFilePath = Path.Combine(Global.DataDir, "CcjRoundConfig.json");
var roundConfig = new CoordinatorRoundConfig(roundConfigFilePath);
roundConfig.LoadOrCreateDefaultFile();
Logger.LogInfo("RoundConfig is successfully initialized.");
- string host = config.GetBitcoinCoreRpcEndPoint().ToString(config.Network.RPCPort);
- var rpc = new RPCClient(
- authenticationString: config.BitcoinRpcConnectionString,
- hostOrUri: host,
- network: config.Network);
-
- var cachedRpc = new CachedRpcClient(rpc, Cache);
- await Global.InitializeAsync(config, roundConfig, cachedRpc, cancellationToken);
+ await Global.InitializeAsync(roundConfig, cancellationToken);
}
private static void TaskScheduler_UnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)

MODIFY
WalletWasabi.Backend/Startup.cs
WalletWasabi.Backend/Startup.cs
@@ -2,21 +2,23 @@ using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
+using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using NBitcoin;
+using NBitcoin.RPC;
using System.Diagnostics.CodeAnalysis;
using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
using WalletWasabi.Backend.Controllers.WabiSabi;
using WalletWasabi.Backend.Middlewares;
+using WalletWasabi.BitcoinCore.Rpc;
using WalletWasabi.Helpers;
using WalletWasabi.Interfaces;
using WalletWasabi.Logging;
+using WalletWasabi.Userfacing;
using WalletWasabi.WabiSabi;
using WalletWasabi.WabiSabi.Models.Serialization;
using WalletWasabi.WebClients;
@@ -37,6 +39,8 @@ public class Startup
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
+ string dataDir = Configuration["datadir"] ?? EnvironmentHelpers.GetDataDir(Path.Combine("WalletWasabi", "Backend"));
+
services.AddMemoryCache();
services.AddMvc(options => options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(BitcoinAddress))))
@@ -69,10 +73,30 @@ public class Startup
services.AddLogging(logging => logging.AddFilter((s, level) => level >= Microsoft.Extensions.Logging.LogLevel.Warning));
services.AddSingleton<IExchangeRateProvider>(new ExchangeRateProvider());
+ services.AddSingleton(serviceProvider =>
+ {
+ string configFilePath = Path.Combine(dataDir, "Config.json");
+ Config config = new(configFilePath);
+ config.LoadOrCreateDefaultFile();
+ return config;
+ });
+
services.AddSingleton<IdempotencyRequestCache>();
-#pragma warning disable CA2000 // Dispose objects before losing scope, reason: https://github.com/dotnet/roslyn-analyzers/issues/3836
- services.AddSingleton(new Global(Configuration["datadir"]));
-#pragma warning restore CA2000 // Dispose objects before losing scope
+ services.AddSingleton(serviceProvider =>
+ {
+ Config config = serviceProvider.GetRequiredService<Config>();
+ string host = config.GetBitcoinCoreRpcEndPoint().ToString(config.Network.RPCPort);
+
+ RPCClient rpcClient = new(
+ authenticationString: config.BitcoinRpcConnectionString,
+ hostOrUri: host,
+ network: config.Network);
+
+ IMemoryCache memoryCache = serviceProvider.GetRequiredService<IMemoryCache>();
+ CachedRpcClient cachedRpc = new(rpcClient, memoryCache);
+
+ return new Global(dataDir, cachedRpc, config);
+ });
services.AddSingleton(serviceProvider =>
{
var global = serviceProvider.GetRequiredService<Global>();

Fix warnings in Backend project (take 3)  (#9028)

* Revert "Revert "Fix warnings in Backend project (take 2) (#8100)""

This reverts commit 98df6af4baec4533eb1d648335f5bc089664b2fb.

* fix