Example #1
0
        public Global()
        {
            DataDir          = EnvironmentHelpers.GetDataDir(Path.Combine("WalletWasabi", "Client"));
            TorLogsFile      = Path.Combine(DataDir, "TorLogs.txt");
            WalletsDir       = Path.Combine(DataDir, "Wallets");
            WalletBackupsDir = Path.Combine(DataDir, "WalletBackups");

            Directory.CreateDirectory(DataDir);
            Directory.CreateDirectory(WalletsDir);
            Directory.CreateDirectory(WalletBackupsDir);
            RpcMonitor = new RpcMonitor(TimeSpan.FromSeconds(7));
        }
Example #2
0
 public RpcFeeProvider(TimeSpan period, IRPCClient rpcClient, RpcMonitor rpcMonitor) : base(period)
 {
     RpcClient  = rpcClient;
     RpcMonitor = rpcMonitor;
 }
Example #3
0
        public 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($"{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);
            }

            UpdateChecker = new UpdateChecker(TimeSpan.FromMinutes(7), 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.");

                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

            var feeProviderList = new List <IFeeProvider>();
            try
            {
                if (Config.StartLocalBitcoinCoreOnStartup)
                {
                    BitcoinCoreNode = await CoreNode
                                      .CreateAsync(
                        new CoreNodeParams(
                            Network,
                            BitcoinStore.MempoolService,
                            Config.LocalBitcoinCoreDataDir,
                            tryRestart : false,
                            tryDeleteDataDir : false,
                            EndPointStrategy.Custom(Config.GetBitcoinP2pEndPoint()),
                            EndPointStrategy.Default(Network, EndPointType.Rpc),
                            txIndex : null,
                            prune : null,
                            userAgent : $"/WasabiClient:{Constants.ClientVersion.ToString()}/"),
                        CancellationToken.None)
                                      .ConfigureAwait(false);

                    RpcMonitor.RpcClient = BitcoinCoreNode.RpcClient;
                    RpcMonitor.Start();

                    RpcFeeProvider = new RpcFeeProvider(TimeSpan.FromMinutes(1), BitcoinCoreNode.RpcClient);
                    RpcFeeProvider.Start();
                    feeProviderList.Add(RpcFeeProvider);
                }
            }
            catch (Exception ex)
            {
                Logger.LogError(ex);
            }

            feeProviderList.Add(Synchronizer);
            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 { })
Example #4
0
        private long _dispose = 0;         // To detect redundant calls

        public async Task DisposeAsync()
        {
            var compareRes = Interlocked.CompareExchange(ref _dispose, 1, 0);

            if (compareRes == 1)
            {
                while (Interlocked.Read(ref _dispose) != 2)
                {
                    await Task.Delay(50);
                }
                return;
            }
            else if (compareRes == 2)
            {
                return;
            }

            try
            {
                await DisposeInWalletDependentServicesAsync();

                if (UpdateChecker != null)
                {
                    await UpdateChecker?.StopAsync();

                    Logger.LogInfo($"{nameof(UpdateChecker)} is stopped.");
                }

                if (FeeProviders != null)
                {
                    FeeProviders.Dispose();
                    Logger.LogInfo($"Disposed {nameof(FeeProviders)}.");
                }

                if (Synchronizer != null)
                {
                    await Synchronizer?.StopAsync();

                    Logger.LogInfo($"{nameof(Synchronizer)} is stopped.");
                }

                if (RpcFeeProvider != null)
                {
                    await RpcFeeProvider.StopAsync();

                    Logger.LogInfo("Stopped synching fees through RPC.");
                }

                if (AddressManagerFilePath != null)
                {
                    IoHelpers.EnsureContainingDirectoryExists(AddressManagerFilePath);
                    if (AddressManager != null)
                    {
                        AddressManager?.SavePeerFile(AddressManagerFilePath, Config.Network);
                        Logger.LogInfo($"{nameof(AddressManager)} is saved to `{AddressManagerFilePath}`.");
                    }
                }

                if (Nodes != null)
                {
                    Nodes?.Disconnect();
                    while (Nodes.ConnectedNodes.Any(x => x.IsConnected))
                    {
                        await Task.Delay(50);
                    }
                    Nodes?.Dispose();
                    Logger.LogInfo($"{nameof(Nodes)} are disposed.");
                }

                if (RegTestMempoolServingNode != null)
                {
                    RegTestMempoolServingNode.Disconnect();
                    Logger.LogInfo($"{nameof(RegTestMempoolServingNode)} is disposed.");
                }

                if (RpcMonitor != null)
                {
                    await RpcMonitor.StopAsync();

                    Logger.LogInfo("Stopped monitoring RPC.");
                }

                if (Config.StopLocalBitcoinCoreOnShutdown && BitcoinCoreNode != null)
                {
                    await BitcoinCoreNode.TryStopAsync().ConfigureAwait(false);
                }

                if (TorManager != null)
                {
                    await TorManager?.StopAsync();

                    Logger.LogInfo($"{nameof(TorManager)} is stopped.");
                }

                if (AsyncMutex.IsAny)
                {
                    try
                    {
                        await AsyncMutex.WaitForAllMutexToCloseAsync();

                        Logger.LogInfo($"{nameof(AsyncMutex)}(es) are stopped.");
                    }
                    catch (Exception ex)
                    {
                        Logger.LogError($"Error during stopping {nameof(AsyncMutex)}: {ex}");
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.LogWarning(ex);
            }
            finally
            {
                Interlocked.Exchange(ref _dispose, 2);
            }
        }