예제 #1
0
 public Global(
     ITorManager torManager,
     IDataDirProvider dataDirProvider,
     Config config,
     UiConfig uiConfig,
     ChaincaseWalletManager walletManager,
     BitcoinStore bitcoinStore,
     ChaincaseSynchronizer synchronizer,
     FeeProviders feeProviders
     )
 {
     _torManager      = torManager;
     _dataDirProvider = dataDirProvider;
     _config          = config;
     _uiConfig        = uiConfig;
     _walletManager   = walletManager;
     _bitcoinStore    = bitcoinStore;
     _synchronizer    = synchronizer;
     _feeProviders    = feeProviders;
     using (BenchmarkLogger.Measure())
     {
         StoppingCts = new CancellationTokenSource();
         Logger.InitializeDefaults(Path.Combine(DataDir, "Logs.txt"));
         _uiConfig.LoadOrCreateDefaultFile();
     }
 }
예제 #2
0
        public async Task InitializeNoWalletAsync(CancellationToken cancellationToken = default)
        {
            AddressManager = null;
            Logger.LogDebug($"Global.InitializeNoWalletAsync(): Waiting for a lock");
            try
            {
                InitializationStarted = true;

                Logger.LogDebug($"Global.InitializeNoWalletAsync(): Got lock");

                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 ChaincaseSynchronizer(Network, BitcoinStore, () => Config.GetCurrentBackendUri(), Config.TorSocks5EndPoint);
                }
                else
                {
                    Synchronizer = new ChaincaseSynchronizer(Network, BitcoinStore, Config.GetFallbackBackendUri(), null);
                }

                #region TorProcessInitialization

                if (Config.UseTor)
                {
                    await TorManager.StartAsync(ensureRunning : false, DataDir);

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

                Logger.LogInfo($"Global.InitializeNoWalletAsync():{nameof(TorManager)} is initialized.");

                #endregion TorProcessInitialization

                #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

                #region FeeProviderInitialization
                // Mirrors #region BitcoinCoreInitialization in WalletWasabi

                var feeProviderList = new List <IFeeProvider>
                {
                    Synchronizer
                };

                FeeProviders = new FeeProviders(feeProviderList);

                #endregion FeeProviderInitialization

                #region MempoolInitialization

                connectionParameters.TemplateBehaviors.Add(BitcoinStore.CreateUntrustedP2pBehavior());

                #endregion MempoolInitialization

                #region AddressManagerInitialization

                AddressManagerBehavior addressManagerBehavior = await addrManTask.ConfigureAwait(false);

                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(NBitcoin.Network.RegTest, bitcoinCoreEndpoint).ConfigureAwait(false);

                        Nodes.ConnectedNodes.Add(node);

                        RegTestMempoolServingNode = await Node.ConnectAsync(NBitcoin.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 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).ConfigureAwait(false);
                    }
                    Nodes = new NodesGroup(Network, connectionParameters, requirements: Constants.NodeRequirements);
                    Nodes.MaximumNodeConnection = 12;
                    RegTestMempoolServingNode   = null;
                }

                Nodes.Connect();
                Logger.LogInfo("Global.InitializeNoWalletAsync(): Start connecting to nodes...");

                var regTestMempoolServingNode = RegTestMempoolServingNode;
                if (regTestMempoolServingNode != null)
                {
                    regTestMempoolServingNode.VersionHandshake();
                    Logger.LogInfo("Global.InitializeNoWalletAsync(): 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("Global.InitializeNoWalletAsync(): Start synchronizing filters...");

                #endregion SynchronizerInitialization

                TransactionBroadcaster = new TransactionBroadcaster(Network, BitcoinStore, Synchronizer, Nodes, WalletManager, null);
                CoinJoinProcessor      = new CoinJoinProcessor(Synchronizer, WalletManager, null);

                #region Blocks provider

                var blockProvider = new CachedBlockProvider(
                    new SmartBlockProvider(
                        new P2pBlockProvider(Nodes, null, Synchronizer, Config.ServiceConfiguration, Network),
                        Cache),
                    new FileSystemBlockRepository(blocksFolderPath, Network));

                #endregion Blocks provider

                WalletManager.RegisterServices(BitcoinStore, Synchronizer, Nodes, Config.ServiceConfiguration, FeeProviders, blockProvider);

                Initialized(this, EventArgs.Empty);
                IsInitialized = true;
            }
예제 #3
0
        public StatusViewModel(Global global, ChaincaseWalletManager walletManager, Config config, UiConfig uiConfig, BitcoinStore bitcoinStore, ChaincaseSynchronizer synchronizer)
        {
            _global        = global;
            _walletManager = walletManager;
            _bitcoinStore  = bitcoinStore;
            _Config        = config;
            _uiConfig      = uiConfig;
            _synchronizer  = synchronizer;
            Backend        = BackendStatus.NotConnected;
            Tor            = TorStatus.NotRunning;
            Peers          = 0;
            BtcPrice       = "$0";
            ActiveStatuses = new StatusSet();
            UseTor         = _Config.UseTor; // Do not make it dynamic, because if you change this config settings only next time will it activate.

            if (_global.IsInitialized)
            {
                OnAppInitialized(this, new AppInitializedEventArgs(_global));
            }
            else
            {
                _global.Initialized += OnAppInitialized;
            }

            _status = ActiveStatuses.WhenAnyValue(x => x.CurrentStatus)
                      .Select(x => x.ToString())
                      .ObserveOn(RxApp.MainThreadScheduler)
                      .ToProperty(this, x => x.Status)
                      .DisposeWith(Disposables);

            // Set number of peers currently connected
            Peers = Tor == TorStatus.NotRunning ? 0 : Nodes.Count;
            // Subscribe to downloading block activity
            Observable.FromEventPattern <bool>(typeof(P2pBlockProvider), nameof(P2pBlockProvider.DownloadingBlockChanged))
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(x => DownloadingBlock = x.EventArgs)
            .DisposeWith(Disposables);

            // Calculate progress precentage
            bool progressReset = true;

            _progressPercent = this.WhenAnyValue(x => x.ActiveStatuses.CurrentStatus, x => x.Peers)
                               .Select(tup =>
            {
                var(status, peers) = tup;
                if (peers == 0 && progressReset)
                {
                    progressReset = false;
                    return(0.01);
                }

                switch (status.Type)
                {
                case StatusType.Ready:
                    progressReset = true;
                    return(1);

                case StatusType.Synchronizing:
                    return(status.Percentage / 200.0 + 0.3);

                case StatusType.Connecting:
                default:
                    return(0.3);
                }
            })
                               .ToProperty(this, x => x.ProgressPercent);

            IDisposable walletCheckingInterval = null;

            Observable.FromEventPattern <bool>(typeof(Wallet), nameof(Wallet.InitializingChanged))
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(x =>
            {
                if (x.EventArgs)
                {
                    TryAddStatus(StatusType.WalletLoading);

                    if (walletCheckingInterval is null)
                    {
                        walletCheckingInterval = Observable.Interval(TimeSpan.FromSeconds(1))
                                                 .ObserveOn(RxApp.MainThreadScheduler)
                                                 .Subscribe(_ =>
                        {
                            var wallet = _walletManager.CurrentWallet;
                            if (wallet is { })
                            {
                                var startingHeight = SmartHeader.GetStartingHeader(wallet.Network).Height;
                                if (wallet.LastProcessedFilter?.Header?.Height is uint lastProcessedFilterHeight &&
                                    lastProcessedFilterHeight > startingHeight &&
                                    _bitcoinStore?.SmartHeaderChain?.TipHeight is uint tipHeight &&
                                    tipHeight > startingHeight)
                                {
                                    var allFilters       = tipHeight - startingHeight;
                                    var processedFilters = lastProcessedFilterHeight - startingHeight;
                                    var perc             = allFilters == 0 ?
                                                           100
                                                : ((decimal)processedFilters / allFilters * 100);
                                    TryAddStatus(StatusType.WalletProcessingFilters, (ushort)perc);
                                }

                                var txProcessor = wallet.TransactionProcessor;
                                if (txProcessor is { })
                                {
                                    var perc = txProcessor.QueuedTxCount == 0 ?
                                               100
                                                : ((decimal)txProcessor.QueuedProcessedTxCount / txProcessor.QueuedTxCount * 100);
                                    TryAddStatus(StatusType.WalletProcessingTransactions, (ushort)perc);
                                }
                            }