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."); }
public async Task InitializeAsync(Config config, CcjRoundConfig roundConfig, RPCClient rpc) { 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.GetBitcoinCoreEndPoint()); // Initialize index building var indexBuilderServiceDir = Path.Combine(DataDir, nameof(IndexBuilderService)); var indexFilePath = Path.Combine(indexBuilderServiceDir, $"Index{RpcClient.Network}.dat"); var utxoSetFilePath = Path.Combine(indexBuilderServiceDir, $"UtxoSet{RpcClient.Network}.dat"); IndexBuilderService = new IndexBuilderService(RpcClient, TrustedNodeNotifyingBehavior, indexFilePath, utxoSetFilePath); Coordinator = new CcjCoordinator(RpcClient.Network, TrustedNodeNotifyingBehavior, Path.Combine(DataDir, nameof(CcjCoordinator)), RpcClient, roundConfig); IndexBuilderService.Synchronize(); Logger.LogInfo <IndexBuilderService>("IndexBuilderService is successfully initialized and started synchronization."); await Coordinator.MakeSureTwoRunningRoundsAsync(); Logger.LogInfo <CcjCoordinator>("Chaumian CoinJoin Coordinator is successfully initialized and started two new rounds."); if (roundConfig.FilePath != null) { RoundConfigWatcher = new ConfigWatcher(RoundConfig); RoundConfigWatcher.Start(TimeSpan.FromSeconds(10), () => { try { Coordinator.UpdateRoundConfig(RoundConfig); Coordinator.AbortAllRoundsInInputRegistration(nameof(ConfigWatcher), $"{nameof(RoundConfig)} has changed."); } catch (Exception ex) { Logger.LogDebug <ConfigWatcher>(ex); } return(Task.CompletedTask); }); // Every 10 seconds check the config Logger.LogInfo <ConfigWatcher>($"{nameof(RoundConfigWatcher)} is successfully started."); } }
public async Task UnsynchronizedBitcoinNodeAsync() { var rpc = new MockRpcClient { OnGetBlockchainInfoAsync = () => Task.FromResult(new BlockchainInfo { Headers = 0, Blocks = 0, InitialBlockDownload = false }), }; var blockNotifier = new BlockNotifier(TimeSpan.MaxValue, rpc); var indexer = new IndexBuilderService(rpc, blockNotifier, "."); indexer.Synchronize(); await Task.Delay(TimeSpan.FromSeconds(1)); //// Assert.False(indexer.IsRunning); // <------------ ERROR: it should have stopped but there is a bug for RegTest Assert.Throws <ArgumentOutOfRangeException>(() => indexer.GetLastFilter()); // There are no filters }
public async static Task InitializeAsync(Network network = null, string rpcuser = null, string rpcpassword = null, RPCClient rpc = null) { _dataDir = null; if (network != null || rpcuser != null || rpcpassword != null) { Config = new Config(network, rpcuser, rpcpassword); } else { await InitializeConfigAsync(); } if (rpc != null) { RpcClient = rpc; } else { RpcClient = new RPCClient( credentials: new RPCCredentialString { UserPassword = new NetworkCredential(Config.BitcoinRpcUser, Config.BitcoinRpcPassword) }, network: Config.Network); } await AssertRpcNodeFullyInitializedAsync(); var indexBuilderServiceDir = Path.Combine(DataDir, nameof(IndexBuilderService)); var indexFilePath = Path.Combine(indexBuilderServiceDir, $"Index{RpcClient.Network}.dat"); var utxoSetFilePath = Path.Combine(indexBuilderServiceDir, $"UtxoSet{RpcClient.Network}.dat"); IndexBuilderService = new IndexBuilderService(RpcClient, indexFilePath, utxoSetFilePath); IndexBuilderService.Synchronize(); }
public async Task FilterBuilderTestAsync() { (_, IRPCClient rpc, _, _, _, _, Backend.Global global) = await Common.InitializeTestEnvironmentAsync(RegTestFixture, 1); var indexBuilderServiceDir = Tests.Common.GetWorkDir(); var indexFilePath = Path.Combine(indexBuilderServiceDir, $"Index{rpc.Network}.dat"); var indexBuilderService = new IndexBuilderService(rpc, global.HostedServices.FirstOrDefault <BlockNotifier>(), indexFilePath); try { indexBuilderService.Synchronize(); // Test initial synchronization. var times = 0; uint256 firstHash = await rpc.GetBlockHashAsync(0); while (indexBuilderService.GetFilterLinesExcluding(firstHash, 101, out _).filters.Count() != 101) { if (times > 500) // 30 sec { throw new TimeoutException($"{nameof(IndexBuilderService)} test timed out."); } await Task.Delay(100); times++; } // Test later synchronization. await rpc.GenerateAsync(10); times = 0; while (indexBuilderService.GetFilterLinesExcluding(firstHash, 111, out bool found5).filters.Count() != 111) { Assert.True(found5); if (times > 500) // 30 sec { throw new TimeoutException($"{nameof(IndexBuilderService)} test timed out."); } await Task.Delay(100); times++; } // Test correct number of filters is received. var hundredthHash = await rpc.GetBlockHashAsync(100); Assert.Equal(11, indexBuilderService.GetFilterLinesExcluding(hundredthHash, 11, out bool found).filters.Count()); Assert.True(found); var bestHash = await rpc.GetBestBlockHashAsync(); Assert.Empty(indexBuilderService.GetFilterLinesExcluding(bestHash, 1, out bool found2).filters); Assert.Empty(indexBuilderService.GetFilterLinesExcluding(uint256.Zero, 1, out bool found3).filters); Assert.False(found3); // Test filter block hashes are correct. var filters = indexBuilderService.GetFilterLinesExcluding(firstHash, 111, out bool found4).filters.ToArray(); Assert.True(found4); for (int i = 0; i < 111; i++) { var expectedHash = await rpc.GetBlockHashAsync(i + 1); var filterModel = filters[i]; Assert.Equal(expectedHash, filterModel.Header.BlockHash); } } finally { if (indexBuilderService is { })
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."); }
public async Task FilterBuilderTestAsync() { using (var builder = await NodeBuilder.CreateAsync()) { await builder.CreateNodeAsync(); await builder.StartAllAsync(); CoreNode regtestNode = builder.Nodes[0]; regtestNode.Generate(101); RPCClient rpc = regtestNode.CreateRpcClient(); var indexBuilderServiceDir = Path.Combine(SharedFixture.DataDir, nameof(IndexBuilderService)); var indexFilePath = Path.Combine(indexBuilderServiceDir, $"Index{rpc.Network}.dat"); var utxoSetFilePath = Path.Combine(indexBuilderServiceDir, $"UtxoSet{rpc.Network}.dat"); var indexBuilderService = new IndexBuilderService(rpc, indexFilePath, utxoSetFilePath); try { indexBuilderService.Synchronize(); // Test initial synchronization. var times = 0; uint256 firstHash = await rpc.GetBlockHashAsync(0); while (indexBuilderService.GetFilterLinesExcluding(firstHash, 102, out _).filters.Count() != 101) { if (times > 500) // 30 sec { throw new TimeoutException($"{nameof(IndexBuilderService)} test timed out."); } await Task.Delay(100); times++; } // Test later synchronization. regtestNode.Generate(10); times = 0; while (indexBuilderService.GetFilterLinesExcluding(firstHash, 112, out bool found5).filters.Count() != 111) { Assert.True(found5); if (times > 500) // 30 sec { throw new TimeoutException($"{nameof(IndexBuilderService)} test timed out."); } await Task.Delay(100); times++; } // Test correct number of filters is received. var hundredthHash = await rpc.GetBlockHashAsync(100); Assert.Equal(11, indexBuilderService.GetFilterLinesExcluding(hundredthHash, 12, out bool found).filters.Count()); Assert.True(found); var bestHash = await rpc.GetBestBlockHashAsync(); Assert.Empty(indexBuilderService.GetFilterLinesExcluding(bestHash, 1, out bool found2).filters); Assert.True(found2); Assert.Empty(indexBuilderService.GetFilterLinesExcluding(uint256.Zero, 1, out bool found3).filters); Assert.False(found3); // Test filter block hashes are correct. var filters = indexBuilderService.GetFilterLinesExcluding(firstHash, 112, out bool found4).filters.ToArray(); Assert.True(found4); for (int i = 0; i < 111; i++) { var expectedHash = await rpc.GetBlockHashAsync(i + 1); var filterModel = FilterModel.FromLine(filters[i], i); Assert.Equal(expectedHash, filterModel.BlockHash); Assert.Null(filterModel.Filter); } } finally { if (indexBuilderService != null) { await indexBuilderService.StopAsync(); } } } }