/// <param name="tcpClient">TCP client connected to Tor SOCKS5 endpoint.</param> /// <param name="transportStream">Transport stream to actually send the data to Tor SOCKS5 endpoint (the difference is SSL).</param> /// <param name="circuit">Tor circuit under which we operate with this TCP connection.</param> /// <param name="allowRecycling">Whether it is allowed to re-use this Tor TCP connection.</param> public TorTcpConnection(TcpClient tcpClient, Stream transportStream, ICircuit circuit, bool allowRecycling) { long id = Interlocked.Increment(ref LastId); string prefix = circuit switch { DefaultCircuit _ => "DC", PersonCircuit _ => "PC", _ => "UC" // Unknown circuit type. }; Name = $"{prefix}#{id:0000}#{circuit.Name[0..10]}";
public Global(string dataDir, Config config, UiConfig uiConfig, WalletManager walletManager) { using (BenchmarkLogger.Measure()) { DataDir = dataDir; Config = config; UiConfig = uiConfig; TorSettings = new TorSettings(DataDir, distributionFolderPath: EnvironmentHelpers.GetFullBaseDirectory(), Config.TerminateTorOnExit, Environment.ProcessId); HostedServices = new HostedServices(); WalletManager = walletManager; var networkWorkFolderPath = Path.Combine(DataDir, "BitcoinStore", Network.ToString()); AllTransactionStore = new AllTransactionStore(networkWorkFolderPath, Network); SmartHeaderChain smartHeaderChain = new(maxChainSize : 20_000); IndexStore = new IndexStore(Path.Combine(networkWorkFolderPath, "IndexStore"), Network, smartHeaderChain); var mempoolService = new MempoolService(); var blocks = new FileSystemBlockRepository(Path.Combine(networkWorkFolderPath, "Blocks"), Network); BitcoinStore = new BitcoinStore(IndexStore, AllTransactionStore, mempoolService, blocks); if (Config.UseTor) { BackendHttpClientFactory = new HttpClientFactory(TorSettings.SocksEndpoint, backendUriGetter: () => Config.GetCurrentBackendUri()); ExternalHttpClientFactory = new HttpClientFactory(TorSettings.SocksEndpoint, backendUriGetter: null); } else { BackendHttpClientFactory = new HttpClientFactory(torEndPoint: null, backendUriGetter: () => Config.GetFallbackBackendUri()); ExternalHttpClientFactory = new HttpClientFactory(torEndPoint: null, backendUriGetter: null); } Synchronizer = new WasabiSynchronizer(BitcoinStore, BackendHttpClientFactory); LegalChecker = new(DataDir); TransactionBroadcaster = new TransactionBroadcaster(Network, BitcoinStore, BackendHttpClientFactory, WalletManager); RoundStateUpdaterCircuit = new PersonCircuit(); Cache = new MemoryCache(new MemoryCacheOptions { SizeLimit = 1_000, ExpirationScanFrequency = TimeSpan.FromSeconds(30) });
public async Task UseCorrectIdentitiesAsync() { using CancellationTokenSource timeoutCts = new(TimeSpan.FromMinutes(1)); ICircuit defaultIdentity = DefaultCircuit.Instance; ICircuit aliceIdentity = new PersonCircuit(); ICircuit bobIdentity = new PersonCircuit(); using TorTcpConnection aliceConnection = new(null !, new MemoryStream(), aliceIdentity, true); using TorTcpConnection bobConnection = new(null !, new MemoryStream(), bobIdentity, true); using TorTcpConnection defaultConnection = new(null !, new MemoryStream(), defaultIdentity, true); Mock <TorTcpConnectionFactory> mockTcpConnectionFactory = new(MockBehavior.Strict, new IPEndPoint(IPAddress.Loopback, 7777)); _ = mockTcpConnectionFactory.Setup(c => c.ConnectAsync(It.IsAny <Uri>(), aliceIdentity, It.IsAny <CancellationToken>())).ReturnsAsync(aliceConnection); _ = mockTcpConnectionFactory.Setup(c => c.ConnectAsync(It.IsAny <Uri>(), bobIdentity, It.IsAny <CancellationToken>())).ReturnsAsync(bobConnection); _ = mockTcpConnectionFactory.Setup(c => c.ConnectAsync(It.IsAny <Uri>(), defaultIdentity, It.IsAny <CancellationToken>())).ReturnsAsync(defaultConnection); TorTcpConnectionFactory tcpConnectionFactory = mockTcpConnectionFactory.Object; // Use implementation of TorHttpPool and only replace SendCoreAsync behavior. Mock <TorHttpPool> mockTorHttpPool = new(MockBehavior.Loose, tcpConnectionFactory) { CallBase = true }; mockTorHttpPool.Setup(x => x.SendCoreAsync(It.IsAny <TorTcpConnection>(), It.IsAny <HttpRequestMessage>(), It.IsAny <CancellationToken>())) .Returns((TorTcpConnection tcpConnection, HttpRequestMessage request, CancellationToken cancellationToken) => { HttpResponseMessage httpResponse = new(HttpStatusCode.OK); if (tcpConnection == aliceConnection) { httpResponse.Content = new StringContent("Alice circuit!"); } else if (tcpConnection == bobConnection) { httpResponse.Content = new StringContent("Bob circuit!"); } else if (tcpConnection == defaultConnection) { httpResponse.Content = new StringContent("Default circuit!"); } else { throw new NotSupportedException(); } return(Task.FromResult(httpResponse)); }); using TorHttpPool pool = mockTorHttpPool.Object; using HttpRequestMessage request = new(HttpMethod.Get, "http://wasabi.backend"); using HttpResponseMessage aliceResponse = await pool.SendAsync(request, aliceIdentity); Assert.Equal("Alice circuit!", await aliceResponse.Content.ReadAsStringAsync(timeoutCts.Token)); using HttpResponseMessage bobResponse = await pool.SendAsync(request, bobIdentity); Assert.Equal("Bob circuit!", await bobResponse.Content.ReadAsStringAsync(timeoutCts.Token)); using HttpResponseMessage defaultResponse = await pool.SendAsync(request, defaultIdentity); Assert.Equal("Default circuit!", await defaultResponse.Content.ReadAsStringAsync(timeoutCts.Token)); mockTcpConnectionFactory.VerifyAll(); }