public async Task NodesDifferAsync()
        {
            using var services1 = new HostedServices();
            using var services2 = new HostedServices();
            var coreNodes = await Task.WhenAll(TestNodeBuilder.CreateAsync(services1, additionalFolder: "0"), TestNodeBuilder.CreateAsync(services2, additionalFolder: "1"));

            await services1.StartAllAsync(CancellationToken.None);

            await services2.StartAllAsync(CancellationToken.None);

            CoreNode node1 = coreNodes[0];
            CoreNode node2 = coreNodes[1];

            try
            {
                Assert.NotEqual(node1.DataDir, node2.DataDir);
                Assert.NotEqual(node1.P2pEndPoint, node2.P2pEndPoint);
                Assert.NotEqual(node1.RpcEndPoint, node2.RpcEndPoint);
            }
            finally
            {
                await services1.StopAllAsync(CancellationToken.None);

                await services2.StopAllAsync(CancellationToken.None);

                await Task.WhenAll(node1.TryStopAsync(), node2.TryStopAsync());
            }
        }
Exemplo n.º 2
0
        public async Task AllFeeEstimateAsync()
        {
            using var services = new HostedServices();
            var coreNode = await TestNodeBuilder.CreateAsync(services);

            await services.StartAllAsync(CancellationToken.None);

            try
            {
                var rpc         = coreNode.RpcClient;
                var estimations = await rpc.EstimateAllFeeAsync(EstimateSmartFeeMode.Conservative, simulateIfRegTest : true);

                Assert.Equal(WalletWasabi.Helpers.Constants.OneDayConfirmationTarget, estimations.Estimations.Count);
                Assert.True(estimations.Estimations.First().Key < estimations.Estimations.Last().Key);
                Assert.True(estimations.Estimations.First().Value > estimations.Estimations.Last().Value);
                Assert.Equal(EstimateSmartFeeMode.Conservative, estimations.Type);
                estimations = await rpc.EstimateAllFeeAsync(EstimateSmartFeeMode.Economical, simulateIfRegTest : true);

                Assert.Equal(145, estimations.Estimations.Count);
                Assert.True(estimations.Estimations.First().Key < estimations.Estimations.Last().Key);
                Assert.True(estimations.Estimations.First().Value > estimations.Estimations.Last().Value);
                Assert.Equal(EstimateSmartFeeMode.Economical, estimations.Type);
            }
            finally
            {
                await services.StopAllAsync(CancellationToken.None);

                await coreNode.TryStopAsync();
            }
        }
Exemplo n.º 3
0
        public async Task MempoolNotifiesAsync()
        {
            using var services = new HostedServices();
            var coreNode = await TestNodeBuilder.CreateAsync(services);

            await services.StartAllAsync(CancellationToken.None);

            using var node = await coreNode.CreateNewP2pNodeAsync();

            try
            {
                var network          = coreNode.Network;
                var rpc              = coreNode.RpcClient;
                var dir              = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName(), EnvironmentHelpers.GetMethodName());
                var indexStore       = new IndexStore(Path.Combine(dir, "indexStore"), network, new SmartHeaderChain());
                var transactionStore = new AllTransactionStore(Path.Combine(dir, "transactionStore"), network);
                var mempoolService   = new MempoolService();
                var blocks           = new FileSystemBlockRepository(Path.Combine(dir, "blocks"), network);
                var bitcoinStore     = new BitcoinStore(indexStore, transactionStore, mempoolService, blocks);
                await bitcoinStore.InitializeAsync();

                await rpc.GenerateAsync(101);

                node.Behaviors.Add(bitcoinStore.CreateUntrustedP2pBehavior());
                node.VersionHandshake();

                var addr = new Key().PubKey.GetSegwitAddress(network);

                var txNum        = 10;
                var eventAwaiter = new EventsAwaiter <SmartTransaction>(
                    h => bitcoinStore.MempoolService.TransactionReceived += h,
                    h => bitcoinStore.MempoolService.TransactionReceived -= h,
                    txNum);

                var txTasks = new List <Task <uint256> >();
                var batch   = rpc.PrepareBatch();
                for (int i = 0; i < txNum; i++)
                {
                    txTasks.Add(batch.SendToAddressAsync(addr, Money.Coins(1)));
                }
                var batchTask = batch.SendBatchAsync();

                var stxs = await eventAwaiter.WaitAsync(TimeSpan.FromSeconds(21));

                await batchTask;
                var   hashes = await Task.WhenAll(txTasks);

                foreach (var stx in stxs)
                {
                    Assert.Contains(stx.GetHash(), hashes);
                }
            }
            finally
            {
                await services.StopAllAsync(CancellationToken.None);

                node.Disconnect();
                await coreNode.TryStopAsync();
            }
        }
        public async Task CanBuildCoreNodeAsync()
        {
            using var services = new HostedServices();
            var coreNode = await TestNodeBuilder.CreateAsync(services);

            await services.StartAllAsync(CancellationToken.None);

            await coreNode.TryStopAsync();

            await services.StopAllAsync(CancellationToken.None);
        }
Exemplo n.º 5
0
        public async Task InitializeAsync(Config config, CoordinatorRoundConfig roundConfig, IRPCClient rpc, 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();

            // Make sure P2P works.
            await InitializeP2pAsync(config.Network, config.GetBitcoinP2pEndPoint(), cancel);

            if (roundConfig.FilePath != null)
            {
                HostedServices.Register(
                    new ConfigWatcher(
                        TimeSpan.FromSeconds(10),                         // Every 10 seconds check the config
                        RoundConfig,
                        () =>
                {
                    try
                    {
                        Coordinator.RoundConfig.UpdateOrDefault(RoundConfig, toFile: false);

                        Coordinator.AbortAllRoundsInInputRegistration($"{nameof(RoundConfig)} has changed.");
                    }
                    catch (Exception ex)
                    {
                        Logger.LogDebug(ex);
                    }
                }),
                    "Config Watcher");
            }

            await HostedServices.StartAllAsync(cancel);

            // Initialize index building
            var indexBuilderServiceDir = Path.Combine(DataDir, "IndexBuilderService");
            var indexFilePath          = Path.Combine(indexBuilderServiceDir, $"Index{RpcClient.Network}.dat");
            var blockNotifier          = HostedServices.FirstOrDefault <BlockNotifier>();

            IndexBuilderService = new IndexBuilderService(RpcClient, blockNotifier, indexFilePath);
            Coordinator         = new Coordinator(RpcClient.Network, blockNotifier, Path.Combine(DataDir, "CcjCoordinator"), RpcClient, roundConfig);
            IndexBuilderService.Synchronize();
            Logger.LogInfo($"{nameof(IndexBuilderService)} is successfully initialized and started synchronization.");

            await Coordinator.MakeSureTwoRunningRoundsAsync();

            Logger.LogInfo("Chaumian CoinJoin Coordinator is successfully initialized and started two new rounds.");
        }
Exemplo n.º 6
0
        public async Task TrustedNotifierNotifiesTxAsync()
        {
            using var services = new HostedServices();
            var coreNode = await TestNodeBuilder.CreateAsync(services);

            await services.StartAllAsync(CancellationToken.None);

            try
            {
                var rpc = coreNode.RpcClient;
                await rpc.GenerateAsync(101);

                var network = rpc.Network;

                var dir = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName(), EnvironmentHelpers.GetMethodName());

                var addr     = new Key().PubKey.GetSegwitAddress(network);
                var notifier = coreNode.MempoolService;

                var txNum          = 10;
                var txEventAwaiter = new EventsAwaiter <SmartTransaction>(
                    h => notifier.TransactionReceived += h,
                    h => notifier.TransactionReceived -= h,
                    txNum);

                var txTasks = new List <Task <uint256> >();
                var batch   = rpc.PrepareBatch();
                for (int i = 0; i < txNum; i++)
                {
                    txTasks.Add(batch.SendToAddressAsync(addr, Money.Coins(1)));
                }
                var batchTask = batch.SendBatchAsync();

                var arrivedTxs = await txEventAwaiter.WaitAsync(TimeSpan.FromSeconds(21));

                await batchTask;
                var   hashes = await Task.WhenAll(txTasks);

                foreach (var hash in arrivedTxs.Select(x => x.GetHash()))
                {
                    Assert.Contains(hash, hashes);
                }
            }
            finally
            {
                await services.StopAllAsync(CancellationToken.None);

                await coreNode.TryStopAsync();
            }
        }
Exemplo n.º 7
0
        public async Task CantDoubleSpendAsync()
        {
            using var services = new HostedServices();
            var coreNode = await TestNodeBuilder.CreateAsync(services);

            await services.StartAllAsync(CancellationToken.None);

            try
            {
                var rpc     = coreNode.RpcClient;
                var network = rpc.Network;

                var walletName = "wallet.dat";
                await rpc.CreateWalletAsync(walletName);

                using var k1 = new Key();
                var blockId = await rpc.GenerateToAddressAsync(1, k1.PubKey.WitHash.GetAddress(network));

                var block = await rpc.GetBlockAsync(blockId[0]);

                var coinBaseTx = block.Transactions[0];

                var tx = Transaction.Create(network);
                tx.Inputs.Add(coinBaseTx, 0);
                using var k2 = new Key();
                tx.Outputs.Add(Money.Coins(49.9999m), k2.PubKey.WitHash.GetAddress(network));
                tx.Sign(k1.GetBitcoinSecret(network), coinBaseTx.Outputs.AsCoins().First());
                var valid = tx.Check();

                var doubleSpend = Transaction.Create(network);
                doubleSpend.Inputs.Add(coinBaseTx, 0);
                using var k3 = new Key();
                doubleSpend.Outputs.Add(Money.Coins(49.998m), k3.PubKey.WitHash.GetAddress(network));
                doubleSpend.Sign(k1.GetBitcoinSecret(network), coinBaseTx.Outputs.AsCoins().First());
                valid = doubleSpend.Check();

                await rpc.GenerateAsync(101);

                var txId = await rpc.SendRawTransactionAsync(tx);

                await Assert.ThrowsAsync <RPCException>(async() => await rpc.SendRawTransactionAsync(doubleSpend));
            }
            finally
            {
                await services.StopAllAsync(CancellationToken.None);

                await coreNode.TryStopAsync();
            }
        }
        public async Task RpcWorksAsync()
        {
            using var services = new HostedServices();
            var coreNode = await TestNodeBuilder.CreateAsync(services);

            await services.StartAllAsync(CancellationToken.None);

            try
            {
                var blockCount = await coreNode.RpcClient.GetBlockCountAsync();

                Assert.Equal(0, blockCount);
            }
            finally
            {
                await services.StopAllAsync(CancellationToken.None);

                await coreNode.TryStopAsync();
            }
        }
Exemplo n.º 9
0
        public async Task VerboseBlockInfoAsync()
        {
            using var services = new HostedServices();
            var coreNode = await TestNodeBuilder.CreateAsync(services);

            await services.StartAllAsync(CancellationToken.None);

            try
            {
                var rpc       = coreNode.RpcClient;
                var blockInfo = await rpc.GetVerboseBlockAsync(coreNode.Network.GenesisHash);

                Assert.NotNull(blockInfo.Transactions.ElementAt(0).Inputs.ElementAt(0).Coinbase);
            }
            finally
            {
                await services.StopAllAsync(CancellationToken.None);

                await coreNode.TryStopAsync();
            }
        }
        public async Task P2pWorksAsync()
        {
            using var services = new HostedServices();
            var coreNode = await TestNodeBuilder.CreateAsync(services);

            await services.StartAllAsync(CancellationToken.None);

            using var node = await coreNode.CreateNewP2pNodeAsync();

            try
            {
                var blocks  = node.GetBlocks(new[] { Network.RegTest.GenesisHash });
                var genesis = Assert.Single(blocks);
                Assert.Equal(genesis.GetHash(), Network.RegTest.GenesisHash);
            }
            finally
            {
                await services.StopAllAsync(CancellationToken.None);

                node.Disconnect();
                await coreNode.TryStopAsync();
            }
        }
Exemplo n.º 11
0
        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 { })
Exemplo n.º 12
0
        public async Task BlockNotifierTestsAsync()
        {
            using var services = new HostedServices();
            var coreNode = await TestNodeBuilder.CreateAsync(services);

            await services.StartAllAsync(CancellationToken.None);

            try
            {
                var           rpc      = coreNode.RpcClient;
                BlockNotifier notifier = services.FirstOrDefault <BlockNotifier>();

                // Make sure we get notification for one block.
                var blockEventAwaiter = new EventAwaiter <Block>(
                    h => notifier.OnBlock += h,
                    h => notifier.OnBlock -= h);

                var hash  = (await rpc.GenerateAsync(1)).First();
                var block = await blockEventAwaiter.WaitAsync(TimeSpan.FromSeconds(21));

                Assert.Equal(hash, block.GetHash());

                // Make sure we get notifications about 10 blocks created at the same time.
                var blockNum           = 10;
                var blockEventsAwaiter = new EventsAwaiter <Block>(
                    h => notifier.OnBlock += h,
                    h => notifier.OnBlock -= h,
                    blockNum);

                var hashes = (await rpc.GenerateAsync(blockNum)).ToArray();

                var arrivedBlocks = (await blockEventsAwaiter.WaitAsync(TimeSpan.FromSeconds(21))).ToArray();

                for (int i = 0; i < hashes.Length; i++)
                {
                    var expected = hashes[i];
                    var actual   = arrivedBlocks[i].GetHash();
                    Assert.Equal(expected, actual);
                }

                // Make sure we get reorg notifications.
                var reorgNum           = 3;
                var newBlockNum        = reorgNum + 1;
                var reorgEventsAwaiter = new EventsAwaiter <uint256>(
                    h => notifier.OnReorg += h,
                    h => notifier.OnReorg -= h,
                    reorgNum);
                blockEventsAwaiter         = new EventsAwaiter <Block>(
                    h => notifier.OnBlock += h,
                    h => notifier.OnBlock -= h,
                    newBlockNum);

                var reorgedHashes = hashes.TakeLast(reorgNum).ToArray();
                await rpc.InvalidateBlockAsync(reorgedHashes[0]);

                var newHashes = (await rpc.GenerateAsync(newBlockNum)).ToArray();

                var reorgedHeaders = (await reorgEventsAwaiter.WaitAsync(TimeSpan.FromSeconds(21))).ToArray();
                var newBlocks      = (await blockEventsAwaiter.WaitAsync(TimeSpan.FromSeconds(21))).ToArray();

                reorgedHashes = reorgedHashes.Reverse().ToArray();
                for (int i = 0; i < reorgedHashes.Length; i++)
                {
                    var expected = reorgedHashes[i];
                    var actual   = reorgedHeaders[i];
                    Assert.Equal(expected, actual);
                }

                for (int i = 0; i < newHashes.Length; i++)
                {
                    var expected = newHashes[i];
                    var actual   = newBlocks[i].GetHash();
                    Assert.Equal(expected, actual);
                }
            }
            finally
            {
                await services.StopAllAsync(CancellationToken.None);

                await coreNode.TryStopAsync();
            }
        }
Exemplo n.º 13
0
        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 { })
Exemplo n.º 14
0
        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 { })
Exemplo n.º 15
0
    public async Task InitializeAsync(Config config, CoordinatorRoundConfig roundConfig, IRPCClient rpc, 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);

        var p2pNode = Guard.NotNull(nameof(P2pNode), P2pNode);

        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);

        Coordinator = new(RpcClient.Network, blockNotifier, Path.Combine(DataDir, "CcjCoordinator"), RpcClient, roundConfig);
        Coordinator.CoinJoinBroadcasted += Coordinator_CoinJoinBroadcasted;

        var coordinator = Guard.NotNull(nameof(Coordinator), Coordinator);

        if (!string.IsNullOrWhiteSpace(roundConfig.FilePath))
        {
            HostedServices.Register <ConfigWatcher>(() =>
                                                    new ConfigWatcher(
                                                        TimeSpan.FromSeconds(10), // Every 10 seconds check the config
                                                        RoundConfig,
                                                        () =>
            {
                try
                {
                    coordinator.RoundConfig.UpdateOrDefault(RoundConfig, toFile: false);

                    coordinator.AbortAllRoundsInInputRegistration($"{nameof(RoundConfig)} has changed.");
                }
                catch (Exception ex)
                {
                    Logger.LogDebug(ex);
                }
            }),
                                                    "Config Watcher");
        }

        CoinJoinIdStore = CoinJoinIdStore.Create(Coordinator.CoinJoinsFilePath, coordinatorParameters.CoinJoinIdStoreFilePath);
        var coinJoinScriptStore = CoinJoinScriptStore.LoadFromFile(coordinatorParameters.CoinJoinScriptStoreFilePath);

        WabiSabiCoordinator = new WabiSabiCoordinator(coordinatorParameters, RpcClient, CoinJoinIdStore, coinJoinScriptStore);
        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.");
    }
Exemplo n.º 16
0
        public async Task MempoolNotifiesAsync()
        {
            using var services = new HostedServices();
            CoreNode coreNode = await TestNodeBuilder.CreateAsync(services);

            await services.StartAllAsync();

            BitcoinStore?bitcoinStore = null;

            using var node = await coreNode.CreateNewP2pNodeAsync();

            try
            {
                string dir              = Common.GetWorkDir();
                var    network          = coreNode.Network;
                var    rpc              = coreNode.RpcClient;
                var    indexStore       = new IndexStore(Path.Combine(dir, "indexStore"), network, new SmartHeaderChain());
                var    transactionStore = new AllTransactionStore(Path.Combine(dir, "transactionStore"), network);
                var    mempoolService   = new MempoolService();
                var    blocks           = new FileSystemBlockRepository(Path.Combine(dir, "blocks"), network);

                // Construct BitcoinStore.
                bitcoinStore = new BitcoinStore(indexStore, transactionStore, mempoolService, blocks);
                await bitcoinStore.InitializeAsync();

                await rpc.GenerateAsync(blockCount : 101);

                node.Behaviors.Add(bitcoinStore.CreateUntrustedP2pBehavior());
                node.VersionHandshake();

                BitcoinWitPubKeyAddress address = new Key().PubKey.GetSegwitAddress(network);

                // Number of transactions to send.
                const int TransactionsCount = 10;

                var eventAwaiter = new EventsAwaiter <SmartTransaction>(
                    subscribe: h => mempoolService.TransactionReceived   += h,
                    unsubscribe: h => mempoolService.TransactionReceived -= h,
                    count: TransactionsCount);

                var        txHashesList = new List <Task <uint256> >();
                IRPCClient rpcBatch     = rpc.PrepareBatch();

                // Add to the batch 10 RPC commands: Send 1 coin to the same address.
                for (int i = 0; i < TransactionsCount; i++)
                {
                    txHashesList.Add(rpcBatch.SendToAddressAsync(address, Money.Coins(1)));
                }

                // Publish the RPC batch.
                Task rpcBatchTask = rpcBatch.SendBatchAsync();

                // Wait until the mempool service receives all the sent transactions.
                IEnumerable <SmartTransaction> mempoolSmartTxs = await eventAwaiter.WaitAsync(TimeSpan.FromSeconds(30));

                await rpcBatchTask;

                // Collect all the transaction hashes of the sent transactions.
                uint256[] hashes = await Task.WhenAll(txHashesList);

                // Check that all the received transaction hashes are in the set of sent transaction hashes.
                foreach (SmartTransaction tx in mempoolSmartTxs)
                {
                    Assert.Contains(tx.GetHash(), hashes);
                }
            }
            finally
            {
                if (bitcoinStore is { } store)
                {
                    await store.DisposeAsync();
                }
                await services.StopAllAsync();

                node.Disconnect();
                await coreNode.TryStopAsync();
            }
        }