public DiscordReadyStartJobHandler(DiscordSocketClient client, IndexBuilderService indexBuilder, Settings settings, Logger logger) { _client = client; _indexBuilder = indexBuilder; _settings = settings; _logger = logger; }
#pragma warning restore CS8618 public IndexBuilderService(Settings settings, Logger logger, Stats stats, GitPusherService gitPusherService, IMediator mediator, ISchedulerFactory schedulerFactory, IServiceProvider diContainer) { _instance = this; _settings = settings; _logger = logger; _stats = stats; _gitPusherService = gitPusherService; _mediator = mediator; _diContainer = diContainer; _scheduler = Task.Run(() => schedulerFactory.GetScheduler()).GetAwaiter().GetResult(); _scheduler.Start(); }
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 void DummyFilterMatchesToFalse() { var rnd = new Random(123456); var blockHash = new byte[32]; rnd.NextBytes(blockHash); var filter = IndexBuilderService.CreateDummyEmptyFilter(new uint256(blockHash)); var scriptPubKeys = Enumerable.Range(0, 1000).Select(x => { var buffer = new byte[20]; rnd.NextBytes(buffer); return(buffer); }); var key = blockHash[0..16];
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 static FilterModel GetStartingFilter(Network network) { var startingHeader = SmartHeader.GetStartingHeader(network); if (network == Network.Main) { return(FilterModel.FromLine($"{startingHeader.Height}:{startingHeader.BlockHash}:02832810ec08a0:{startingHeader.PrevHash}:{startingHeader.EpochBlockTime}")); } else if (network == Network.TestNet) { return(FilterModel.FromLine($"{startingHeader.Height}:{startingHeader.BlockHash}:00000000000f0d5edcaeba823db17f366be49a80d91d15b77747c2e017b8c20a:{startingHeader.PrevHash}:{startingHeader.EpochBlockTime}")); } else if (network == Network.RegTest) { GolombRiceFilter filter = IndexBuilderService.CreateDummyEmptyFilter(startingHeader.BlockHash); return(FilterModel.FromLine($"{startingHeader.Height}:{startingHeader.BlockHash}:{filter}:{startingHeader.PrevHash}:{startingHeader.EpochBlockTime}")); } else { throw new NotSupportedNetworkException(network); } }
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 FilterDownloaderTestAsync() { (_, IRPCClient rpc, _, _, _, BitcoinStore bitcoinStore, _) = await Common.InitializeTestEnvironmentAsync(RegTestFixture, 1); var httpClientFactory = new HttpClientFactory(torEndPoint: null, backendUriGetter: () => new Uri(RegTestFixture.BackendEndPoint)); var synchronizer = new WasabiSynchronizer(rpc.Network, bitcoinStore, httpClientFactory); try { synchronizer.Start(requestInterval: TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5), 1000); var blockCount = await rpc.GetBlockCountAsync() + 1; // Plus one because of the zeroth. // Test initial synchronization. var times = 0; int filterCount; while ((filterCount = bitcoinStore.SmartHeaderChain.HashCount) < blockCount) { if (times > 500) // 30 sec { throw new TimeoutException($"{nameof(WasabiSynchronizer)} test timed out. Needed filters: {blockCount}, got only: {filterCount}."); } await Task.Delay(100); times++; } Assert.Equal(blockCount, bitcoinStore.SmartHeaderChain.HashCount); // Test later synchronization. await RegTestFixture.BackendRegTestNode.GenerateAsync(10); times = 0; while ((filterCount = bitcoinStore.SmartHeaderChain.HashCount) < blockCount + 10) { if (times > 500) // 30 sec { throw new TimeoutException($"{nameof(WasabiSynchronizer)} test timed out. Needed filters: {blockCount + 10}, got only: {filterCount}."); } await Task.Delay(100); times++; } // Test correct number of filters is received. Assert.Equal(blockCount + 10, bitcoinStore.SmartHeaderChain.HashCount); // Test filter block hashes are correct. var filterList = new List <FilterModel>(); await bitcoinStore.IndexStore.ForeachFiltersAsync(async x => { filterList.Add(x); await Task.CompletedTask; }, new Height(0)); FilterModel[] filters = filterList.ToArray(); for (int i = 0; i < 101; i++) { var expectedHash = await rpc.GetBlockHashAsync(i); var filter = filters[i]; Assert.Equal(i, (int)filter.Header.Height); Assert.Equal(expectedHash, filter.Header.BlockHash); Assert.Equal(IndexBuilderService.CreateDummyEmptyFilter(expectedHash).ToString(), filter.Filter.ToString()); } } finally { if (synchronizer is { })
public ForceRunCommand(IndexBuilderService builder) { _builder = builder; }
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(); } } } }
public RemoveSourceCommand(Settings settings, IndexBuilderService indexBuilder) { _settings = settings; _indexBuilder = indexBuilder; }
public AddSourceCommand(Logger logger, Settings settings, IndexBuilderService indexBuilder) { _logger = logger; _settings = settings; _indexBuilder = indexBuilder; }
public async Task ReorgTestAsync() { (string password, IRPCClient rpc, Network network, _, _, BitcoinStore bitcoinStore, Backend.Global global) = await Common.InitializeTestEnvironmentAsync(RegTestFixture, 1); var keyManager = KeyManager.CreateNew(out _, password, network); // Mine some coins, make a few bech32 transactions then make it confirm. await rpc.GenerateAsync(1); var key = keyManager.GenerateNewKey(SmartLabel.Empty, KeyState.Clean, isInternal: false); var tx2 = await rpc.SendToAddressAsync(key.GetP2wpkhAddress(network), Money.Coins(0.1m)); key = keyManager.GenerateNewKey(SmartLabel.Empty, KeyState.Clean, isInternal: false); var tx3 = await rpc.SendToAddressAsync(key.GetP2wpkhAddress(network), Money.Coins(0.1m)); var tx4 = await rpc.SendToAddressAsync(key.GetP2pkhAddress(network), Money.Coins(0.1m)); var tx5 = await rpc.SendToAddressAsync(key.GetP2shOverP2wpkhAddress(network), Money.Coins(0.1m)); var tx1 = await rpc.SendToAddressAsync(key.GetP2wpkhAddress(network), Money.Coins(0.1m), replaceable : true); await rpc.GenerateAsync(2); // Generate two, so we can test for two reorg var node = RegTestFixture.BackendRegTestNode; using HttpClientFactory httpClientFactory = new(torEndPoint : null, backendUriGetter : () => new Uri(RegTestFixture.BackendEndPoint)); WasabiSynchronizer synchronizer = new(bitcoinStore, httpClientFactory); try { synchronizer.Start(requestInterval: TimeSpan.FromSeconds(3), 1000); var reorgAwaiter = new EventsAwaiter <FilterModel>( h => bitcoinStore.IndexStore.Reorged += h, h => bitcoinStore.IndexStore.Reorged -= h, 2); // Test initial synchronization. await WaitForIndexesToSyncAsync(global, TimeSpan.FromSeconds(90), bitcoinStore); var tip = await rpc.GetBestBlockHashAsync(); Assert.Equal(tip, bitcoinStore.SmartHeaderChain.TipHash); var tipBlock = await rpc.GetBlockHeaderAsync(tip); Assert.Equal(tipBlock.HashPrevBlock, bitcoinStore.SmartHeaderChain.GetChain().Select(x => x.header.BlockHash).ToArray()[bitcoinStore.SmartHeaderChain.HashCount - 2]); // Test synchronization after fork. await rpc.InvalidateBlockAsync(tip); // Reorg 1 tip = await rpc.GetBestBlockHashAsync(); await rpc.InvalidateBlockAsync(tip); // Reorg 2 var tx1bumpRes = await rpc.BumpFeeAsync(tx1); // RBF it await rpc.GenerateAsync(5); await WaitForIndexesToSyncAsync(global, TimeSpan.FromSeconds(90), bitcoinStore); var hashes = bitcoinStore.SmartHeaderChain.GetChain().Select(x => x.header.BlockHash).ToArray(); Assert.DoesNotContain(tip, hashes); Assert.DoesNotContain(tipBlock.HashPrevBlock, hashes); tip = await rpc.GetBestBlockHashAsync(); Assert.Equal(tip, bitcoinStore.SmartHeaderChain.TipHash); var filterList = new List <FilterModel>(); await bitcoinStore.IndexStore.ForeachFiltersAsync(async x => { filterList.Add(x); await Task.CompletedTask; }, new Height(0)); var filterTip = filterList.Last(); Assert.Equal(tip, filterTip.Header.BlockHash); // Test filter block hashes are correct after fork. var blockCountIncludingGenesis = await rpc.GetBlockCountAsync() + 1; filterList.Clear(); await bitcoinStore.IndexStore.ForeachFiltersAsync(async x => { filterList.Add(x); await Task.CompletedTask; }, new Height(0)); FilterModel[] filters = filterList.ToArray(); for (int i = 0; i < blockCountIncludingGenesis; i++) { var expectedHash = await rpc.GetBlockHashAsync(i); var filter = filters[i]; Assert.Equal(i, (int)filter.Header.Height); Assert.Equal(expectedHash, filter.Header.BlockHash); if (i < 101) // Later other tests may fill the filter. { Assert.Equal(IndexBuilderService.CreateDummyEmptyFilter(expectedHash).ToString(), filter.Filter.ToString()); } } // Test the serialization, too. tip = await rpc.GetBestBlockHashAsync(); var blockHash = tip; for (var i = 0; i < hashes.Length; i++) { var block = await rpc.GetBlockHeaderAsync(blockHash); Assert.Equal(blockHash, hashes[hashes.Length - i - 1]); blockHash = block.HashPrevBlock; } // Assert reorg happened exactly as many times as we reorged. await reorgAwaiter.WaitAsync(TimeSpan.FromSeconds(10)); } finally { await synchronizer.StopAsync(); } }