public static async Task InitializeWalletServiceAsync(KeyManager keyManager) { while (!Initialized) { await Task.Delay(100); } if (Config.UseTor.Value) { ChaumianClient = new CcjClient(Synchronizer, Network, keyManager, () => Config.GetCurrentBackendUri(), Config.GetTorSocks5EndPoint()); } else { ChaumianClient = new CcjClient(Synchronizer, Network, keyManager, Config.GetFallbackBackendUri(), null); } WalletService = new WalletService(BitcoinStore, keyManager, Synchronizer, ChaumianClient, MemPoolService, Nodes, DataDir, Config.ServiceConfiguration); ChaumianClient.Start(); Logger.LogInfo("Start Chaumian CoinJoin service..."); using (CancelWalletServiceInitialization = new CancellationTokenSource()) { Logger.LogInfo("Starting WalletService..."); await WalletService.InitializeAsync(CancelWalletServiceInitialization.Token); Logger.LogInfo("WalletService started."); } CancelWalletServiceInitialization = null; // Must make it null explicitly, because dispose won't make it null. WalletService.Coins.CollectionChanged += Coins_CollectionChanged; }
public Global(string dataDir, string torLogsFile, Config config, UiConfig uiConfig, WalletManager walletManager) { using (BenchmarkLogger.Measure()) { CrashReporter = new CrashReporter(); StoppingCts = new CancellationTokenSource(); DataDir = dataDir; Config = config; UiConfig = uiConfig; TorSettings = new TorSettings(DataDir, torLogsFile, distributionFolderPath: EnvironmentHelpers.GetFullBaseDirectory()); Logger.InitializeDefaults(Path.Combine(DataDir, "Logs.txt")); HostedServices = new HostedServices(); WalletManager = walletManager; LegalDocuments = LegalDocuments.TryLoadAgreed(DataDir); WalletManager.OnDequeue += WalletManager_OnDequeue; WalletManager.WalletRelevantTransactionProcessed += WalletManager_WalletRelevantTransactionProcessed; var networkWorkFolderPath = Path.Combine(DataDir, "BitcoinStore", Network.ToString()); var transactionStore = new AllTransactionStore(networkWorkFolderPath, Network); var indexStore = new IndexStore(Path.Combine(networkWorkFolderPath, "IndexStore"), Network, new SmartHeaderChain()); var mempoolService = new MempoolService(); var blocks = new FileSystemBlockRepository(Path.Combine(networkWorkFolderPath, "Blocks"), Network); BitcoinStore = new BitcoinStore(indexStore, transactionStore, mempoolService, blocks); SingleInstanceChecker = new SingleInstanceChecker(Network); if (Config.UseTor) { Synchronizer = new WasabiSynchronizer(Network, BitcoinStore, () => Config.GetCurrentBackendUri(), Config.TorSocks5EndPoint); } else { Synchronizer = new WasabiSynchronizer(Network, BitcoinStore, Config.GetFallbackBackendUri(), null); } } }
public static async Task InitializeNoWalletAsync() { WalletService = null; ChaumianClient = null; AddressManager = null; TorManager = null; #region ConfigInitialization Config = new Config(Path.Combine(DataDir, "Config.json")); await Config.LoadOrCreateDefaultFileAsync(); Logger.LogInfo <Config>("Config is successfully initialized."); #endregion ConfigInitialization BitcoinStore = new BitcoinStore(); var bstoreInitTask = BitcoinStore.InitializeAsync(Path.Combine(DataDir, "BitcoinStore"), Network); var hwiInitTask = HwiProcessManager.InitializeAsync(DataDir, Network); var addressManagerFolderPath = Path.Combine(DataDir, "AddressManager"); AddressManagerFilePath = Path.Combine(addressManagerFolderPath, $"AddressManager{Network}.dat"); var blocksFolderPath = Path.Combine(DataDir, $"Blocks{Network}"); var connectionParameters = new NodeConnectionParameters(); if (Config.UseTor.Value) { Synchronizer = new WasabiSynchronizer(Network, BitcoinStore, () => Config.GetCurrentBackendUri(), Config.GetTorSocks5EndPoint()); } else { Synchronizer = new WasabiSynchronizer(Network, BitcoinStore, Config.GetFallbackBackendUri(), null); } UpdateChecker = new UpdateChecker(Synchronizer.WasabiClient); #region ProcessKillSubscription AppDomain.CurrentDomain.ProcessExit += async(s, e) => await TryDesperateDequeueAllCoinsAsync(); Console.CancelKeyPress += async(s, e) => { e.Cancel = true; Logger.LogWarning("Process was signaled for killing.", nameof(Global)); KillRequested = true; await TryDesperateDequeueAllCoinsAsync(); Dispatcher.UIThread.PostLogException(() => { Application.Current?.MainWindow?.Close(); }); }; #endregion ProcessKillSubscription #region TorProcessInitialization if (Config.UseTor.Value) { TorManager = new TorProcessManager(Config.GetTorSocks5EndPoint(), TorLogsFile); } else { TorManager = TorProcessManager.Mock(); } TorManager.Start(false, DataDir); var fallbackRequestTestUri = new Uri(Config.GetFallbackBackendUri(), "/api/software/versions"); TorManager.StartMonitor(TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(7), DataDir, fallbackRequestTestUri); Logger.LogInfo <TorProcessManager>($"{nameof(TorProcessManager)} is initialized."); #endregion TorProcessInitialization #region AddressManagerInitialization var needsToDiscoverPeers = true; if (Network == Network.RegTest) { AddressManager = new AddressManager(); Logger.LogInfo <AddressManager>($"Fake {nameof(AddressManager)} is initialized on the RegTest."); } else { try { AddressManager = AddressManager.LoadPeerFile(AddressManagerFilePath); // The most of the times we don't need to discover new peers. Instead, we can connect to // some of those that we already discovered in the past. In this case we assume that we // assume that discovering new peers could be necessary if out address manager has less // than 500 addresses. A 500 addresses could be okay because previously we tried with // 200 and only one user reported he/she was not able to connect (there could be many others, // of course). // On the other side, increasing this number forces users that do not need to discover more peers // to spend resources (CPU/bandwith) to discover new peers. needsToDiscoverPeers = Config.UseTor == true || AddressManager.Count < 500; Logger.LogInfo <AddressManager>($"Loaded {nameof(AddressManager)} from `{AddressManagerFilePath}`."); } catch (DirectoryNotFoundException ex) { Logger.LogInfo <AddressManager>($"{nameof(AddressManager)} did not exist at `{AddressManagerFilePath}`. Initializing new one."); Logger.LogTrace <AddressManager>(ex); AddressManager = new AddressManager(); } catch (FileNotFoundException ex) { Logger.LogInfo <AddressManager>($"{nameof(AddressManager)} did not exist at `{AddressManagerFilePath}`. Initializing new one."); Logger.LogTrace <AddressManager>(ex); AddressManager = new AddressManager(); } catch (OverflowException ex) { // https://github.com/zkSNACKs/WalletWasabi/issues/712 Logger.LogInfo <AddressManager>($"{nameof(AddressManager)} has thrown `{nameof(OverflowException)}`. Attempting to autocorrect."); File.Delete(AddressManagerFilePath); Logger.LogTrace <AddressManager>(ex); AddressManager = new AddressManager(); Logger.LogInfo <AddressManager>($"{nameof(AddressManager)} autocorrection is successful."); } catch (FormatException ex) { // https://github.com/zkSNACKs/WalletWasabi/issues/880 Logger.LogInfo <AddressManager>($"{nameof(AddressManager)} has thrown `{nameof(FormatException)}`. Attempting to autocorrect."); File.Delete(AddressManagerFilePath); Logger.LogTrace <AddressManager>(ex); AddressManager = new AddressManager(); Logger.LogInfo <AddressManager>($"{nameof(AddressManager)} autocorrection is successful."); } } var addressManagerBehavior = new AddressManagerBehavior(AddressManager) { Mode = needsToDiscoverPeers ? AddressManagerBehaviorMode.Discover : AddressManagerBehaviorMode.None }; connectionParameters.TemplateBehaviors.Add(addressManagerBehavior); #endregion AddressManagerInitialization #region MempoolInitialization MemPoolService = new MemPoolService(); connectionParameters.TemplateBehaviors.Add(new MemPoolBehavior(MemPoolService)); #endregion MempoolInitialization #region HwiProcessInitialization try { await hwiInitTask; } catch (Exception ex) { Logger.LogError(ex, nameof(Global)); } #endregion HwiProcessInitialization #region BitcoinStoreInitialization await bstoreInitTask; #endregion BitcoinStoreInitialization #region P2PInitialization if (Network == Network.RegTest) { Nodes = new NodesGroup(Network, requirements: Constants.NodeRequirements); try { Node node = await Node.ConnectAsync(Network.RegTest, new IPEndPoint(IPAddress.Loopback, 18444)); Nodes.ConnectedNodes.Add(node); RegTestMemPoolServingNode = await Node.ConnectAsync(Network.RegTest, new IPEndPoint(IPAddress.Loopback, 18444)); RegTestMemPoolServingNode.Behaviors.Add(new MemPoolBehavior(MemPoolService)); } catch (SocketException ex) { Logger.LogError(ex, nameof(Global)); } } else { if (Config.UseTor is true) { // onlyForOnionHosts: false - Connect to clearnet IPs through Tor, too. connectionParameters.TemplateBehaviors.Add(new SocksSettingsBehavior(Config.GetTorSocks5EndPoint(), onlyForOnionHosts: false, networkCredential: null, streamIsolation: true)); // allowOnlyTorEndpoints: true - Connect only to onions and don't connect to clearnet IPs at all. // This of course makes the first setting unneccessary, but it's better if that's around, in case someone wants to tinker here. connectionParameters.EndpointConnector = new DefaultEndpointConnector(allowOnlyTorEndpoints: Network == Network.Main); await AddKnownBitcoinFullNodeAsHiddenServiceAsync(AddressManager); } Nodes = new NodesGroup(Network, connectionParameters, requirements: Constants.NodeRequirements); RegTestMemPoolServingNode = null; } Nodes.Connect(); Logger.LogInfo("Start connecting to nodes..."); if (RegTestMemPoolServingNode != null) { RegTestMemPoolServingNode.VersionHandshake(); Logger.LogInfo("Start connecting to mempool serving regtest node..."); } #endregion P2PInitialization #region SynchronizerInitialization var requestInterval = TimeSpan.FromSeconds(30); if (Network == Network.RegTest) { requestInterval = TimeSpan.FromSeconds(5); } int maxFiltSyncCount = Network == Network.Main ? 1000 : 10000; // On testnet, filters are empty, so it's faster to query them together Synchronizer.Start(requestInterval, TimeSpan.FromMinutes(5), maxFiltSyncCount); Logger.LogInfo("Start synchronizing filters..."); #endregion SynchronizerInitialization Initialized = true; }
public async Task InitializeNoWalletAsync() { InitializationStarted = true; AddressManager = null; var cancel = StoppingCts.Token; try { await SingleInstanceChecker.CheckAsync().ConfigureAwait(false); Cache = new MemoryCache(new MemoryCacheOptions { SizeLimit = 1_000, ExpirationScanFrequency = TimeSpan.FromSeconds(30) }); var bstoreInitTask = BitcoinStore.InitializeAsync(); var addressManagerFolderPath = Path.Combine(DataDir, "AddressManager"); AddressManagerFilePath = Path.Combine(addressManagerFolderPath, $"AddressManager{Network}.dat"); var addrManTask = InitializeAddressManagerBehaviorAsync(); var userAgent = Constants.UserAgents.RandomElement(); var connectionParameters = new NodeConnectionParameters { UserAgent = userAgent }; HostedServices.Register(new UpdateChecker(TimeSpan.FromMinutes(7), Synchronizer), "Software Update Checker"); HostedServices.Register(new SystemAwakeChecker(WalletManager), "System Awake Checker"); #region ProcessKillSubscription AppDomain.CurrentDomain.ProcessExit += async(s, e) => await DisposeAsync().ConfigureAwait(false); Console.CancelKeyPress += async(s, e) => { e.Cancel = true; Logger.LogWarning("Process was signaled for killing.", nameof(Global)); await DisposeAsync().ConfigureAwait(false); }; #endregion ProcessKillSubscription cancel.ThrowIfCancellationRequested(); #region TorProcessInitialization if (Config.UseTor) { using (BenchmarkLogger.Measure(operationName: "TorProcessManager.Start")) { TorManager = new TorProcessManager(TorSettings, Config.TorSocks5EndPoint); await TorManager.StartAsync(ensureRunning : true).ConfigureAwait(false); } var fallbackRequestTestUri = new Uri(Config.GetFallbackBackendUri(), "/api/software/versions"); TorManager.StartMonitor(TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(7), fallbackRequestTestUri); } else { TorSocks5EndPoint = null; } Logger.LogInfo($"{nameof(TorProcessManager)} is initialized."); #endregion TorProcessInitialization cancel.ThrowIfCancellationRequested(); #region BitcoinStoreInitialization await bstoreInitTask.ConfigureAwait(false); // Make sure that the height of the wallets will not be better than the current height of the filters. WalletManager.SetMaxBestHeight(BitcoinStore.IndexStore.SmartHeaderChain.TipHeight); #endregion BitcoinStoreInitialization cancel.ThrowIfCancellationRequested(); #region BitcoinCoreInitialization try { if (Config.StartLocalBitcoinCoreOnStartup) { BitcoinCoreNode = await CoreNode .CreateAsync( new CoreNodeParams( Network, BitcoinStore.MempoolService, HostedServices, Config.LocalBitcoinCoreDataDir, tryRestart : false, tryDeleteDataDir : false, EndPointStrategy.Default(Network, EndPointType.P2p), EndPointStrategy.Default(Network, EndPointType.Rpc), txIndex : null, prune : null, mempoolReplacement : "fee,optin", userAgent : $"/WasabiClient:{Constants.ClientVersion}/", fallbackFee : null, // ToDo: Maybe we should have it, not only for tests? Cache), cancel) .ConfigureAwait(false); } } catch (Exception ex) { Logger.LogError(ex); } await HostedServices.StartAllAsync(cancel).ConfigureAwait(false); var rpcFeeProvider = HostedServices.FirstOrDefault <RpcFeeProvider>(); FeeProviders = new FeeProviders(Synchronizer, rpcFeeProvider); #endregion BitcoinCoreInitialization cancel.ThrowIfCancellationRequested(); #region MempoolInitialization connectionParameters.TemplateBehaviors.Add(BitcoinStore.CreateUntrustedP2pBehavior()); #endregion MempoolInitialization cancel.ThrowIfCancellationRequested(); #region AddressManagerInitialization AddressManagerBehavior addressManagerBehavior = await addrManTask.ConfigureAwait(false); connectionParameters.TemplateBehaviors.Add(addressManagerBehavior); #endregion AddressManagerInitialization cancel.ThrowIfCancellationRequested(); #region P2PInitialization if (Network == Network.RegTest) { Nodes = new NodesGroup(Network, requirements: Constants.NodeRequirements); try { EndPoint bitcoinCoreEndpoint = Config.GetBitcoinP2pEndPoint(); Node node = await Node.ConnectAsync(Network.RegTest, bitcoinCoreEndpoint).ConfigureAwait(false); Nodes.ConnectedNodes.Add(node); RegTestMempoolServingNode = await Node.ConnectAsync(Network.RegTest, bitcoinCoreEndpoint).ConfigureAwait(false); RegTestMempoolServingNode.Behaviors.Add(BitcoinStore.CreateUntrustedP2pBehavior()); } catch (SocketException ex) { Logger.LogError(ex); } } else { if (Config.UseTor) { // onlyForOnionHosts: false - Connect to clearnet IPs through Tor, too. connectionParameters.TemplateBehaviors.Add(new SocksSettingsBehavior(Config.TorSocks5EndPoint, onlyForOnionHosts: false, networkCredential: null, streamIsolation: true)); // allowOnlyTorEndpoints: true - Connect only to onions and do not connect to clearnet IPs at all. // This of course makes the first setting unnecessary, but it's better if that's around, in case someone wants to tinker here. connectionParameters.EndpointConnector = new DefaultEndpointConnector(allowOnlyTorEndpoints: Network == Network.Main); await AddKnownBitcoinFullNodeAsHiddenServiceAsync(AddressManager).ConfigureAwait(false); } Nodes = new NodesGroup(Network, connectionParameters, requirements: Constants.NodeRequirements); Nodes.MaximumNodeConnection = 12; RegTestMempoolServingNode = null; } Nodes.Connect(); Logger.LogInfo("Start connecting to nodes..."); var regTestMempoolServingNode = RegTestMempoolServingNode; if (regTestMempoolServingNode is { })
public static void InitializeNoWallet() { WalletService = null; ChaumianClient = null; AppDomain.CurrentDomain.ProcessExit += async(s, e) => await TryDesperateDequeueAllCoinsAsync(); Console.CancelKeyPress += async(s, e) => { e.Cancel = true; Logger.LogWarning("Process was signaled for killing.", nameof(Global)); await TryDesperateDequeueAllCoinsAsync(); Dispatcher.UIThread.Post(() => { Application.Current.MainWindow.Close(); }); }; var addressManagerFolderPath = Path.Combine(DataDir, "AddressManager"); AddressManagerFilePath = Path.Combine(addressManagerFolderPath, $"AddressManager{Network}.dat"); var blocksFolderPath = Path.Combine(DataDir, $"Blocks{Network}"); var connectionParameters = new NodeConnectionParameters(); AddressManager = null; TorManager = null; TorManager = new TorProcessManager(Config.GetTorSocks5EndPoint(), TorLogsFile); TorManager.Start(false, DataDir); var fallbackRequestTestUri = new Uri(Config.GetFallbackBackendUri(), "/api/software/versions"); TorManager.StartMonitor(TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(7), DataDir, fallbackRequestTestUri); Logger.LogInfo <TorProcessManager>($"{nameof(TorProcessManager)} is initialized."); var needsToDiscoverPeers = true; if (Network == Network.RegTest) { AddressManager = new AddressManager(); Logger.LogInfo <AddressManager>($"Fake {nameof(AddressManager)} is initialized on the RegTest."); } else { try { AddressManager = AddressManager.LoadPeerFile(AddressManagerFilePath); // The most of the times we don't need to discover new peers. Instead, we can connect to // some of those that we already discovered in the past. In this case we assume that we // assume that discovering new peers could be necessary if out address manager has less // than 500 addresses. A 500 addresses could be okay because previously we tried with // 200 and only one user reported he/she was not able to connect (there could be many others, // of course). // On the other side, increasing this number forces users that do not need to discover more peers // to spend resources (CPU/bandwith) to discover new peers. needsToDiscoverPeers = AddressManager.Count < 500; Logger.LogInfo <AddressManager>($"Loaded {nameof(AddressManager)} from `{AddressManagerFilePath}`."); } catch (DirectoryNotFoundException ex) { Logger.LogInfo <AddressManager>($"{nameof(AddressManager)} did not exist at `{AddressManagerFilePath}`. Initializing new one."); Logger.LogTrace <AddressManager>(ex); AddressManager = new AddressManager(); } catch (FileNotFoundException ex) { Logger.LogInfo <AddressManager>($"{nameof(AddressManager)} did not exist at `{AddressManagerFilePath}`. Initializing new one."); Logger.LogTrace <AddressManager>(ex); AddressManager = new AddressManager(); } catch (OverflowException ex) { // https://github.com/zkSNACKs/WalletWasabi/issues/712 Logger.LogInfo <AddressManager>($"{nameof(AddressManager)} has thrown `{nameof(OverflowException)}`. Attempting to autocorrect."); File.Delete(AddressManagerFilePath); Logger.LogTrace <AddressManager>(ex); AddressManager = new AddressManager(); Logger.LogInfo <AddressManager>($"{nameof(AddressManager)} autocorrection is successful."); } catch (FormatException ex) { // https://github.com/zkSNACKs/WalletWasabi/issues/880 Logger.LogInfo <AddressManager>($"{nameof(AddressManager)} has thrown `{nameof(FormatException)}`. Attempting to autocorrect."); File.Delete(AddressManagerFilePath); Logger.LogTrace <AddressManager>(ex); AddressManager = new AddressManager(); Logger.LogInfo <AddressManager>($"{nameof(AddressManager)} autocorrection is successful."); } } var addressManagerBehavior = new AddressManagerBehavior(AddressManager) { Mode = needsToDiscoverPeers ? AddressManagerBehaviorMode.Discover : AddressManagerBehaviorMode.None }; connectionParameters.TemplateBehaviors.Add(addressManagerBehavior); MemPoolService = new MemPoolService(); connectionParameters.TemplateBehaviors.Add(new MemPoolBehavior(MemPoolService)); if (Network == Network.RegTest) { Nodes = new NodesGroup(Network, requirements: Constants.NodeRequirements); try { Node node = Node.Connect(Network.RegTest, new IPEndPoint(IPAddress.Loopback, 18444)); Nodes.ConnectedNodes.Add(node); RegTestMemPoolServingNode = Node.Connect(Network.RegTest, new IPEndPoint(IPAddress.Loopback, 18444)); RegTestMemPoolServingNode.Behaviors.Add(new MemPoolBehavior(MemPoolService)); } catch (SocketException ex) { Logger.LogError(ex, nameof(Global)); } } else { Nodes = new NodesGroup(Network, connectionParameters, requirements: Constants.NodeRequirements); RegTestMemPoolServingNode = null; } Synchronizer = new WasabiSynchronizer(Network, IndexFilePath, Config.GetCurrentBackendUri(), Config.GetTorSocks5EndPoint()); UpdateChecker = new UpdateChecker(Synchronizer.WasabiClient); Nodes.Connect(); Logger.LogInfo("Start connecting to nodes..."); if (!(RegTestMemPoolServingNode is null)) { RegTestMemPoolServingNode.VersionHandshake(); Logger.LogInfo("Start connecting to mempool serving regtest node..."); } var requestInterval = TimeSpan.FromSeconds(30); if (Network == Network.RegTest) { requestInterval = TimeSpan.FromSeconds(5); } Synchronizer.Start(requestInterval, TimeSpan.FromMinutes(5), 1000); Logger.LogInfo("Start synchronizing filters..."); }
public async Task InitializeNoWalletAsync() { try { WalletService = null; ChaumianClient = null; AddressManager = null; TorManager = null; #region ConfigInitialization Config = new Config(Path.Combine(DataDir, "Config.json")); await Config.LoadOrCreateDefaultFileAsync(); Logger.LogInfo($"{nameof(Config)} is successfully initialized."); #endregion ConfigInitialization BitcoinStore = new BitcoinStore(); var bstoreInitTask = BitcoinStore.InitializeAsync(Path.Combine(DataDir, "BitcoinStore"), Network); var addressManagerFolderPath = Path.Combine(DataDir, "AddressManager"); AddressManagerFilePath = Path.Combine(addressManagerFolderPath, $"AddressManager{Network}.dat"); var addrManTask = InitializeAddressManagerBehaviorAsync(); var blocksFolderPath = Path.Combine(DataDir, $"Blocks{Network}"); var connectionParameters = new NodeConnectionParameters { UserAgent = "/Satoshi:0.18.1/" }; if (Config.UseTor) { Synchronizer = new WasabiSynchronizer(Network, BitcoinStore, () => Config.GetCurrentBackendUri(), Config.TorSocks5EndPoint); } else { Synchronizer = new WasabiSynchronizer(Network, BitcoinStore, Config.GetFallbackBackendUri(), null); } HostedServices.Register(new UpdateChecker(TimeSpan.FromMinutes(7), Synchronizer.WasabiClient), "Software Update Checker"); #region ProcessKillSubscription AppDomain.CurrentDomain.ProcessExit += async(s, e) => await TryDesperateDequeueAllCoinsAsync(); Console.CancelKeyPress += async(s, e) => { e.Cancel = true; Logger.LogWarning("Process was signaled for killing."); KillRequested = true; await TryDesperateDequeueAllCoinsAsync(); Dispatcher.UIThread.PostLogException(() => { var window = (Application.Current.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime).MainWindow; window?.Close(); }); await DisposeAsync(); Logger.LogSoftwareStopped("Wasabi"); }; #endregion ProcessKillSubscription #region TorProcessInitialization if (Config.UseTor) { TorManager = new TorProcessManager(Config.TorSocks5EndPoint, TorLogsFile); } else { TorManager = TorProcessManager.Mock(); } TorManager.Start(false, DataDir); var fallbackRequestTestUri = new Uri(Config.GetFallbackBackendUri(), "/api/software/versions"); TorManager.StartMonitor(TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(7), DataDir, fallbackRequestTestUri); Logger.LogInfo($"{nameof(TorProcessManager)} is initialized."); #endregion TorProcessInitialization #region BitcoinStoreInitialization await bstoreInitTask; #endregion BitcoinStoreInitialization #region BitcoinCoreInitialization try { if (Config.StartLocalBitcoinCoreOnStartup) { BitcoinCoreNode = await CoreNode .CreateAsync( new CoreNodeParams( Network, BitcoinStore.MempoolService, HostedServices, Config.LocalBitcoinCoreDataDir, tryRestart : false, tryDeleteDataDir : false, EndPointStrategy.Default(Network, EndPointType.P2p), EndPointStrategy.Default(Network, EndPointType.Rpc), txIndex : null, prune : null, userAgent : $"/WasabiClient:{Constants.ClientVersion.ToString()}/"), CancellationToken.None) .ConfigureAwait(false); } } catch (Exception ex) { Logger.LogError(ex); } await HostedServices.StartAllAsync(StoppingCts.Token).ConfigureAwait(false); var feeProviderList = new List <IFeeProvider> { Synchronizer }; var rpcFeeProvider = HostedServices.FirstOrDefault <RpcFeeProvider>(); if (rpcFeeProvider is { }) { feeProviderList.Insert(0, rpcFeeProvider); } FeeProviders = new FeeProviders(feeProviderList); #endregion BitcoinCoreInitialization #region MempoolInitialization connectionParameters.TemplateBehaviors.Add(BitcoinStore.CreateUntrustedP2pBehavior()); #endregion MempoolInitialization #region AddressManagerInitialization AddressManagerBehavior addressManagerBehavior = await addrManTask; connectionParameters.TemplateBehaviors.Add(addressManagerBehavior); #endregion AddressManagerInitialization #region P2PInitialization if (Network == Network.RegTest) { Nodes = new NodesGroup(Network, requirements: Constants.NodeRequirements); try { EndPoint bitcoinCoreEndpoint = Config.GetBitcoinP2pEndPoint(); Node node = await Node.ConnectAsync(Network.RegTest, bitcoinCoreEndpoint).ConfigureAwait(false); Nodes.ConnectedNodes.Add(node); RegTestMempoolServingNode = await Node.ConnectAsync(Network.RegTest, bitcoinCoreEndpoint).ConfigureAwait(false); RegTestMempoolServingNode.Behaviors.Add(BitcoinStore.CreateUntrustedP2pBehavior()); } catch (SocketException ex) { Logger.LogError(ex); } } else { if (Config.UseTor is true) { // onlyForOnionHosts: false - Connect to clearnet IPs through Tor, too. connectionParameters.TemplateBehaviors.Add(new SocksSettingsBehavior(Config.TorSocks5EndPoint, onlyForOnionHosts: false, networkCredential: null, streamIsolation: true)); // allowOnlyTorEndpoints: true - Connect only to onions and do not connect to clearnet IPs at all. // This of course makes the first setting unnecessary, but it's better if that's around, in case someone wants to tinker here. connectionParameters.EndpointConnector = new DefaultEndpointConnector(allowOnlyTorEndpoints: Network == Network.Main); await AddKnownBitcoinFullNodeAsHiddenServiceAsync(AddressManager); } Nodes = new NodesGroup(Network, connectionParameters, requirements: Constants.NodeRequirements); RegTestMempoolServingNode = null; } Nodes.Connect(); Logger.LogInfo("Start connecting to nodes..."); var regTestMempoolServingNode = RegTestMempoolServingNode; if (regTestMempoolServingNode is { })
public async Task InitializeNoWalletAsync() { InitializationStarted = true; AddressManager = null; TorManager = null; var cancel = StoppingCts.Token; try { await SingleInstanceChecker.CheckAsync().ConfigureAwait(false); Cache = new MemoryCache(new MemoryCacheOptions { SizeLimit = 1_000, ExpirationScanFrequency = TimeSpan.FromSeconds(30) }); var bstoreInitTask = BitcoinStore.InitializeAsync(); var addressManagerFolderPath = Path.Combine(DataDir, "AddressManager"); AddressManagerFilePath = Path.Combine(addressManagerFolderPath, $"AddressManager{Network}.dat"); var addrManTask = InitializeAddressManagerBehaviorAsync(); var blocksFolderPath = Path.Combine(DataDir, $"Blocks{Network}"); var userAgent = Constants.UserAgents.RandomElement(); var connectionParameters = new NodeConnectionParameters { UserAgent = userAgent }; if (Config.UseTor) { Synchronizer = new WasabiSynchronizer(Network, BitcoinStore, () => Config.GetCurrentBackendUri(), Config.TorSocks5EndPoint); } else { Synchronizer = new WasabiSynchronizer(Network, BitcoinStore, Config.GetFallbackBackendUri(), null); } HostedServices.Register(new UpdateChecker(TimeSpan.FromMinutes(7), Synchronizer), "Software Update Checker"); #region ProcessKillSubscription AppDomain.CurrentDomain.ProcessExit += async(s, e) => await DisposeAsync().ConfigureAwait(false); Console.CancelKeyPress += async(s, e) => { e.Cancel = true; Logger.LogWarning("Process was signaled for killing.", nameof(Global)); await DisposeAsync().ConfigureAwait(false); }; #endregion ProcessKillSubscription cancel.ThrowIfCancellationRequested(); #region TorProcessInitialization if (Config.UseTor) { TorManager = new TorProcessManager(Config.TorSocks5EndPoint, TorLogsFile); } else { TorManager = TorProcessManager.Mock(); } TorManager.Start(false, DataDir); var fallbackRequestTestUri = new Uri(Config.GetFallbackBackendUri(), "/api/software/versions"); TorManager.StartMonitor(TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(7), DataDir, fallbackRequestTestUri); Logger.LogInfo($"{nameof(TorProcessManager)} is initialized."); #endregion TorProcessInitialization cancel.ThrowIfCancellationRequested(); #region BitcoinStoreInitialization await bstoreInitTask.ConfigureAwait(false); // Make sure that the height of the wallets will not be better than the current height of the filters. WalletManager.SetMaxBestHeight(BitcoinStore.IndexStore.SmartHeaderChain.TipHeight); #endregion BitcoinStoreInitialization cancel.ThrowIfCancellationRequested(); #region BitcoinCoreInitialization try { if (Config.StartLocalBitcoinCoreOnStartup) { BitcoinCoreNode = await CoreNode .CreateAsync( new CoreNodeParams( Network, BitcoinStore.MempoolService, HostedServices, Config.LocalBitcoinCoreDataDir, tryRestart : false, tryDeleteDataDir : false, EndPointStrategy.Default(Network, EndPointType.P2p), EndPointStrategy.Default(Network, EndPointType.Rpc), txIndex : null, prune : null, userAgent : $"/WasabiClient:{Constants.ClientVersion}/", Cache), cancel) .ConfigureAwait(false); } } catch (Exception ex) { Logger.LogError(ex); } await HostedServices.StartAllAsync(cancel).ConfigureAwait(false); var feeProviderList = new List <IFeeProvider> { Synchronizer }; var rpcFeeProvider = HostedServices.FirstOrDefault <RpcFeeProvider>(); if (rpcFeeProvider is { })
public static async Task InitializeNoWalletAsync() { WalletService = null; ChaumianClient = null; AddressManager = null; TorManager = null; #region ConfigInitialization Config = new Config(Path.Combine(DataDir, "Config.json")); await Config.LoadOrCreateDefaultFileAsync(); Logger.LogInfo <Config>("Config is successfully initialized."); #endregion ConfigInitialization BitcoinStore = new BitcoinStore(); var bstoreInitTask = BitcoinStore.InitializeAsync(Path.Combine(DataDir, "BitcoinStore"), Network); var hwiInitTask = HwiProcessManager.InitializeAsync(DataDir, Network); var addressManagerFolderPath = Path.Combine(DataDir, "AddressManager"); AddressManagerFilePath = Path.Combine(addressManagerFolderPath, $"AddressManager{Network}.dat"); var addrManTask = InitializeAddressManagerBehaviorAsync(); var blocksFolderPath = Path.Combine(DataDir, $"Blocks{Network}"); var connectionParameters = new NodeConnectionParameters(); if (Config.UseTor.Value) { Synchronizer = new WasabiSynchronizer(Network, BitcoinStore, () => Config.GetCurrentBackendUri(), Config.GetTorSocks5EndPoint()); } else { Synchronizer = new WasabiSynchronizer(Network, BitcoinStore, Config.GetFallbackBackendUri(), null); } UpdateChecker = new UpdateChecker(Synchronizer.WasabiClient); #region ProcessKillSubscription AppDomain.CurrentDomain.ProcessExit += async(s, e) => await TryDesperateDequeueAllCoinsAsync(); Console.CancelKeyPress += async(s, e) => { e.Cancel = true; await StopAndExitAsync(); }; #endregion ProcessKillSubscription #region TorProcessInitialization if (Config.UseTor.Value) { TorManager = new TorProcessManager(Config.GetTorSocks5EndPoint(), TorLogsFile); } else { TorManager = TorProcessManager.Mock(); } TorManager.Start(false, DataDir); var fallbackRequestTestUri = new Uri(Config.GetFallbackBackendUri(), "/api/software/versions"); TorManager.StartMonitor(TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(7), DataDir, fallbackRequestTestUri); Logger.LogInfo <TorProcessManager>($"{nameof(TorProcessManager)} is initialized."); #endregion TorProcessInitialization #region MempoolInitialization MemPoolService = new MemPoolService(); connectionParameters.TemplateBehaviors.Add(new MemPoolBehavior(MemPoolService)); #endregion MempoolInitialization #region HwiProcessInitialization try { await hwiInitTask; } catch (Exception ex) { Logger.LogError(ex, nameof(Global)); } #endregion HwiProcessInitialization #region BitcoinStoreInitialization await bstoreInitTask; #endregion BitcoinStoreInitialization #region AddressManagerInitialization AddressManagerBehavior addressManagerBehavior = await addrManTask; connectionParameters.TemplateBehaviors.Add(addressManagerBehavior); #endregion AddressManagerInitialization #region P2PInitialization if (Network == Network.RegTest) { Nodes = new NodesGroup(Network, requirements: Constants.NodeRequirements); try { Node node = await Node.ConnectAsync(Network.RegTest, new IPEndPoint(IPAddress.Loopback, 18444)); Nodes.ConnectedNodes.Add(node); RegTestMemPoolServingNode = await Node.ConnectAsync(Network.RegTest, new IPEndPoint(IPAddress.Loopback, 18444)); RegTestMemPoolServingNode.Behaviors.Add(new MemPoolBehavior(MemPoolService)); } catch (SocketException ex) { Logger.LogError(ex, nameof(Global)); } } else { if (Config.UseTor is true) { // onlyForOnionHosts: false - Connect to clearnet IPs through Tor, too. connectionParameters.TemplateBehaviors.Add(new SocksSettingsBehavior(Config.GetTorSocks5EndPoint(), onlyForOnionHosts: false, networkCredential: null, streamIsolation: true)); // allowOnlyTorEndpoints: true - Connect only to onions and don't connect to clearnet IPs at all. // This of course makes the first setting unneccessary, but it's better if that's around, in case someone wants to tinker here. connectionParameters.EndpointConnector = new DefaultEndpointConnector(allowOnlyTorEndpoints: Network == Network.Main); await AddKnownBitcoinFullNodeAsHiddenServiceAsync(AddressManager); } Nodes = new NodesGroup(Network, connectionParameters, requirements: Constants.NodeRequirements); RegTestMemPoolServingNode = null; } Nodes.Connect(); Logger.LogInfo("Start connecting to nodes..."); if (RegTestMemPoolServingNode != null) { RegTestMemPoolServingNode.VersionHandshake(); Logger.LogInfo("Start connecting to mempool serving regtest node..."); } #endregion P2PInitialization #region SynchronizerInitialization var requestInterval = TimeSpan.FromSeconds(30); if (Network == Network.RegTest) { requestInterval = TimeSpan.FromSeconds(5); } int maxFiltSyncCount = Network == Network.Main ? 1000 : 10000; // On testnet, filters are empty, so it's faster to query them together Synchronizer.Start(requestInterval, TimeSpan.FromMinutes(5), maxFiltSyncCount); Logger.LogInfo("Start synchronizing filters..."); #endregion SynchronizerInitialization #region JsonRpcServerInitialization var jsonRpcServerConfig = new JsonRpcServerConfiguration(Config); if (jsonRpcServerConfig.IsEnabled) { RpcServer = new JsonRpcServer(jsonRpcServerConfig); RpcServer.Start(); } #endregion JsonRpcServerInitialization Initialized = true; }
public async Task InitializeWalletServiceAsync(KeyManager keyManager) { using (_cancelWalletServiceInitialization = new CancellationTokenSource()) { var token = _cancelWalletServiceInitialization.Token; while (!Initialized) { await Task.Delay(100, token); } if (Config.UseTor) { ChaumianClient = new CcjClient(Synchronizer, Network, keyManager, () => Config.GetCurrentBackendUri(), Config.TorSocks5EndPoint); } else { ChaumianClient = new CcjClient(Synchronizer, Network, keyManager, Config.GetFallbackBackendUri(), null); } try { keyManager.CorrectBlockHeights(BitcoinStore.HashChain); // Block heights are wrong sometimes. It's a hack. We have to retroactively fix existing wallets, but also we have to figure out where we ruin the block heights. } catch (Exception ex) // Whatever this is not critical, but let's log it. { Logger.LogWarning(ex, nameof(Global)); } WalletService = new WalletService(BitcoinStore, keyManager, Synchronizer, ChaumianClient, MempoolService, Nodes, DataDir, Config.ServiceConfiguration); ChaumianClient.Start(); Logger.LogInfo("Start Chaumian CoinJoin service..."); Logger.LogInfo($"Starting {nameof(WalletService)}..."); await WalletService.InitializeAsync(token); Logger.LogInfo($"{nameof(WalletService)} started."); token.ThrowIfCancellationRequested(); WalletService.Coins.CollectionChanged += Coins_CollectionChanged; } _cancelWalletServiceInitialization = null; // Must make it null explicitly, because dispose won't make it null. }
public Global(string dataDir, string torLogsFile, Config config, UiConfig uiConfig, WalletManager walletManager) { using (BenchmarkLogger.Measure()) { StoppingCts = new CancellationTokenSource(); DataDir = dataDir; Config = config; UiConfig = uiConfig; TorSettings = new TorSettings(DataDir, torLogsFile, distributionFolderPath: EnvironmentHelpers.GetFullBaseDirectory()); HostedServices = new HostedServices(); WalletManager = walletManager; WalletManager.OnDequeue += WalletManager_OnDequeue; WalletManager.WalletRelevantTransactionProcessed += WalletManager_WalletRelevantTransactionProcessed; var networkWorkFolderPath = Path.Combine(DataDir, "BitcoinStore", Network.ToString()); var transactionStore = new AllTransactionStore(networkWorkFolderPath, Network); var indexStore = new IndexStore(Path.Combine(networkWorkFolderPath, "IndexStore"), Network, new SmartHeaderChain()); var mempoolService = new MempoolService(); var blocks = new FileSystemBlockRepository(Path.Combine(networkWorkFolderPath, "Blocks"), Network); BitcoinStore = new BitcoinStore(indexStore, transactionStore, mempoolService, blocks); HttpClientFactory httpClientFactory = Config.UseTor ? new HttpClientFactory(Config.TorSocks5EndPoint, backendUriGetter: () => Config.GetCurrentBackendUri()) : new HttpClientFactory(torEndPoint: null, backendUriGetter: () => Config.GetFallbackBackendUri()); Synchronizer = new WasabiSynchronizer(Network, BitcoinStore, httpClientFactory); LegalChecker = new(DataDir); } }
public static void InitializeNoWallet() { WalletService = null; ChaumianClient = null; AppDomain.CurrentDomain.ProcessExit += async(s, e) => await TryDesperateDequeueAllCoinsAsync(); Console.CancelKeyPress += async(s, e) => { e.Cancel = true; Logger.LogWarning("Process was signaled for killing.", nameof(Global)); await TryDesperateDequeueAllCoinsAsync(); Dispatcher.UIThread.Post(() => { Application.Current.MainWindow.Close(); }); }; var addressManagerFolderPath = Path.Combine(DataDir, "AddressManager"); AddressManagerFilePath = Path.Combine(addressManagerFolderPath, $"AddressManager{Network}.dat"); var blocksFolderPath = Path.Combine(DataDir, $"Blocks{Network}"); var connectionParameters = new NodeConnectionParameters(); AddressManager = null; TorManager = null; TorManager = new TorProcessManager(Config.GetTorSocks5EndPoint(), TorLogsFile); TorManager.Start(false, DataDir); var fallbackRequestTestUri = new Uri(Config.GetFallbackBackendUri(), "/api/software/versions"); TorManager.StartMonitor(TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(7), DataDir, fallbackRequestTestUri); Logger.LogInfo <TorProcessManager>($"{nameof(TorProcessManager)} is initialized."); var needsToDiscoverPeers = true; if (Network == Network.RegTest) { AddressManager = new AddressManager(); Logger.LogInfo <AddressManager>($"Fake {nameof(AddressManager)} is initialized on the RegTest."); } else { try { AddressManager = AddressManager.LoadPeerFile(AddressManagerFilePath); needsToDiscoverPeers = AddressManager.Count < 200; Logger.LogInfo <AddressManager>($"Loaded {nameof(AddressManager)} from `{AddressManagerFilePath}`."); } catch (DirectoryNotFoundException ex) { Logger.LogInfo <AddressManager>($"{nameof(AddressManager)} did not exist at `{AddressManagerFilePath}`. Initializing new one."); Logger.LogTrace <AddressManager>(ex); AddressManager = new AddressManager(); } catch (FileNotFoundException ex) { Logger.LogInfo <AddressManager>($"{nameof(AddressManager)} did not exist at `{AddressManagerFilePath}`. Initializing new one."); Logger.LogTrace <AddressManager>(ex); AddressManager = new AddressManager(); } catch (OverflowException ex) { // https://github.com/zkSNACKs/WalletWasabi/issues/712 Logger.LogInfo <AddressManager>($"{nameof(AddressManager)} has thrown `{nameof(OverflowException)}`. Attempting to autocorrect."); File.Delete(AddressManagerFilePath); Logger.LogTrace <AddressManager>(ex); AddressManager = new AddressManager(); Logger.LogInfo <AddressManager>($"{nameof(AddressManager)} autocorrection is successful."); } catch (FormatException ex) { // https://github.com/zkSNACKs/WalletWasabi/issues/880 Logger.LogInfo <AddressManager>($"{nameof(AddressManager)} has thrown `{nameof(FormatException)}`. Attempting to autocorrect."); File.Delete(AddressManagerFilePath); Logger.LogTrace <AddressManager>(ex); AddressManager = new AddressManager(); Logger.LogInfo <AddressManager>($"{nameof(AddressManager)} autocorrection is successful."); } } var addressManagerBehavior = new AddressManagerBehavior(AddressManager); addressManagerBehavior.Mode = needsToDiscoverPeers ? AddressManagerBehaviorMode.Discover : AddressManagerBehaviorMode.None; connectionParameters.TemplateBehaviors.Add(addressManagerBehavior); MemPoolService = new MemPoolService(); connectionParameters.TemplateBehaviors.Add(new MemPoolBehavior(MemPoolService)); if (Network == Network.RegTest | Network.Name == "chaincoin-reg") //todopw: extend { Nodes = new NodesGroup(Network, requirements: Constants.NodeRequirements); try { // todopw: extend Node node; if (Network.Name == "chaincoin-reg") { node = Node.Connect(NBitcoin.Altcoins.Chaincoin.Instance.Regtest, new IPEndPoint(IPAddress.Loopback, 18444)); } else { node = Node.Connect(Network.RegTest, new IPEndPoint(IPAddress.Loopback, 18444)); } Nodes.ConnectedNodes.Add(node); RegTestMemPoolServingNode = Node.Connect(Network.RegTest, new IPEndPoint(IPAddress.Loopback, 18444)); RegTestMemPoolServingNode.Behaviors.Add(new MemPoolBehavior(MemPoolService)); } catch (SocketException ex) { Logger.LogError(ex, nameof(Global)); } } else { Nodes = new NodesGroup(Network, connectionParameters, requirements: Constants.NodeRequirements); RegTestMemPoolServingNode = null; } // todopw: Error UpdateChecker just chc - No connection could be made because the target machine actively refused it 127.0.0.1:37127 Synchronizer = new WasabiSynchronizer(Network, IndexFilePath, Config.GetCurrentBackendUri(), Config.GetTorSocks5EndPoint()); UpdateChecker = new UpdateChecker(Synchronizer.WasabiClient); Nodes.Connect(); Logger.LogInfo("Start connecting to nodes..."); if (!(RegTestMemPoolServingNode is null)) { RegTestMemPoolServingNode.VersionHandshake(); Logger.LogInfo("Start connecting to mempool serving regtest node..."); } var requestInterval = TimeSpan.FromSeconds(30); if (Network == Network.RegTest || Network.Name == "chaincoin-reg") // todopw: extend { requestInterval = TimeSpan.FromSeconds(5); } Synchronizer.Start(requestInterval, TimeSpan.FromMinutes(5), 1000); Logger.LogInfo("Start synchronizing filters..."); }
public Global(string dataDir, Config config, UiConfig uiConfig, WalletManager walletManager) { using (BenchmarkLogger.Measure()) { DataDir = dataDir; Config = config; UiConfig = uiConfig; TorSettings = new TorSettings(DataDir, distributionFolderPath: EnvironmentHelpers.GetFullBaseDirectory(), Config.TerminateTorOnExit, Environment.ProcessId); HostedServices = new HostedServices(); WalletManager = walletManager; WalletManager.OnDequeue += WalletManager_OnDequeue; WalletManager.WalletRelevantTransactionProcessed += WalletManager_WalletRelevantTransactionProcessed; var networkWorkFolderPath = Path.Combine(DataDir, "BitcoinStore", Network.ToString()); var transactionStore = new AllTransactionStore(networkWorkFolderPath, Network); var indexStore = new IndexStore(Path.Combine(networkWorkFolderPath, "IndexStore"), Network, new SmartHeaderChain()); var mempoolService = new MempoolService(); var blocks = new FileSystemBlockRepository(Path.Combine(networkWorkFolderPath, "Blocks"), Network); BitcoinStore = new BitcoinStore(indexStore, transactionStore, mempoolService, blocks); if (Config.UseTor) { BackendHttpClientFactory = new HttpClientFactory(TorSettings.SocksEndpoint, backendUriGetter: () => Config.GetCurrentBackendUri()); ExternalHttpClientFactory = new HttpClientFactory(TorSettings.SocksEndpoint, backendUriGetter: null); } else { BackendHttpClientFactory = new HttpClientFactory(torEndPoint: null, backendUriGetter: () => Config.GetFallbackBackendUri()); ExternalHttpClientFactory = new HttpClientFactory(torEndPoint: null, backendUriGetter: null); } Synchronizer = new WasabiSynchronizer(BitcoinStore, BackendHttpClientFactory); LegalChecker = new(DataDir); TransactionBroadcaster = new TransactionBroadcaster(Network, BitcoinStore, BackendHttpClientFactory, WalletManager); } }