private async void Synchronizer_ResponseArrivedAsync(object sender, SynchronizeResponse response) { try { using (await ProcessLock.LockAsync()) { var unconfirmedCoinJoinHashes = response.UnconfirmedCoinJoins; if (!unconfirmedCoinJoinHashes.Any()) { return; } var txsNotKnownByAWallet = WalletManager.FilterUnknownCoinjoins(unconfirmedCoinJoinHashes); using var client = new WasabiClient(Synchronizer.WasabiClient.TorClient.DestinationUriAction, Synchronizer.WasabiClient.TorClient.TorSocks5EndPoint); var unconfirmedCoinJoins = await client.GetTransactionsAsync(Synchronizer.Network, txsNotKnownByAWallet, CancellationToken.None).ConfigureAwait(false); foreach (var tx in unconfirmedCoinJoins.Select(x => new SmartTransaction(x, Height.Mempool))) { if (RpcClient is null || await TryBroadcastTransactionWithRpcAsync(tx).ConfigureAwait(false) || (await RpcClient.TestAsync().ConfigureAwait(false)) is { }) // If the test throws exception then I believe it, because RPC is down and the backend is the god. { WalletManager.ProcessCoinJoin(tx); } }
private async Task BroadcastTransactionToBackendAsync(SmartTransaction transaction) { Logger.LogInfo("Broadcasting with backend..."); using (TorHttpClient torHttpClient = Synchronizer.HttpClientFactory.NewBackendTorHttpClient(isolateStream: true)) { var client = new WasabiClient(torHttpClient); try { await client.BroadcastAsync(transaction).ConfigureAwait(false); } catch (HttpRequestException ex2) when(RpcErrorTools.IsSpentError(ex2.Message)) { if (transaction.Transaction.Inputs.Count == 1) // If we tried to only spend one coin, then we can mark it as spent. If there were more coins, then we do not know. { OutPoint input = transaction.Transaction.Inputs.First().PrevOut; foreach (var coin in WalletManager.CoinsByOutPoint(input)) { coin.SpentAccordingToBackend = true; } } throw; } } BelieveTransaction(transaction); Logger.LogInfo($"Transaction is successfully broadcasted to backend: {transaction.GetHash()}."); }
public async Task GetExchangeRateAsync(NetworkType networkType) // xunit wtf: If this function is called GetExchangeRatesAsync, it'll stuck on 1 CPU VMs (Manjuro, Fedora) { using var client = new WasabiClient(LiveServerTestsFixture.UriMappings[networkType], Global.Instance.TorSocks5Endpoint); var exchangeRates = await client.GetExchangeRatesAsync(); Assert.True(exchangeRates.NotNullAndNotEmpty()); }
public async Task GetFeesAsync(NetworkType networkType) { using var client = new WasabiClient(LiveServerTestsFixture.UriMappings[networkType], Global.Instance.TorSocks5Endpoint); var feeEstimationPairs = await client.GetFeesAsync(1000); Assert.True(feeEstimationPairs.NotNullAndNotEmpty()); }
private async Task BroadcastTransactionToBackendAsync(SmartTransaction transaction) { Logger.LogInfo("Broadcasting with backend..."); using (var client = new WasabiClient(Synchronizer.WasabiClient.TorClient.DestinationUriAction, Synchronizer.WasabiClient.TorClient.TorSocks5EndPoint)) { try { await client.BroadcastAsync(transaction).ConfigureAwait(false); } catch (HttpRequestException ex2) when(ex2.Message.Contains("bad-txns-inputs-missingorspent", StringComparison.InvariantCultureIgnoreCase) || ex2.Message.Contains("missing-inputs", StringComparison.InvariantCultureIgnoreCase) || ex2.Message.Contains("txn-mempool-conflict", StringComparison.InvariantCultureIgnoreCase)) { if (transaction.Transaction.Inputs.Count == 1) // If we tried to only spend one coin, then we can mark it as spent. If there were more coins, then we do not know. { OutPoint input = transaction.Transaction.Inputs.First().PrevOut; lock (WalletServicesLock) { foreach (var walletService in AliveWalletServices) { SmartCoin coin = walletService.Coins.GetByOutPoint(input); if (coin != default) { coin.SpentAccordingToBackend = true; } } } } } } BelieveTransaction(transaction); Logger.LogInfo($"Transaction is successfully broadcasted to backend: {transaction.GetHash()}."); }
public async Task GetTransactionsTestAsync() { var mempool = Enumerable.Range(0, 1_100).Select(_ => CreateTransaction()).ToArray(); Task <HttpResponseMessage> FakeServerCode(HttpMethod method, string action, NameValueCollection parameters, string body) { Assert.True(parameters.Count <= 10); IEnumerable <uint256> requestedTxIds = parameters["transactionIds"].Split(",").Select(x => uint256.Parse(x)); IEnumerable <string> result = mempool.Where(tx => requestedTxIds.Contains(tx.GetHash())).Select(tx => tx.ToHex()); var response = new HttpResponseMessage(HttpStatusCode.OK); response.Content = new StringContent(JsonConvert.SerializeObject(result)); return(Task.FromResult(response)); }; var torHttpClient = new MockTorHttpClient(); torHttpClient.OnSendAsync = FakeServerCode; var client = new WasabiClient(torHttpClient); Assert.Empty(WasabiClient.TransactionCache); // Requests one transaction var searchedTxId = mempool[0].GetHash(); var txs = await client.GetTransactionsAsync(Network.Main, new[] { searchedTxId }, CancellationToken.None); Assert.Equal(searchedTxId, txs.First().GetHash()); Assert.NotEmpty(WasabiClient.TransactionCache); Assert.True(WasabiClient.TransactionCache.ContainsKey(searchedTxId)); // Requests 20 transaction var searchedTxIds = mempool[..20].Select(x => x.GetHash());
public async Task GetClientVersionAsync() { using var client = new WasabiClient(new Uri(RegTestFixture.BackendEndPoint), null); var uptodate = await client.CheckUpdatesAsync(CancellationToken.None); Assert.True(uptodate.BackendCompatible); Assert.True(uptodate.ClientUpToDate); }
public async Task GetClientVersionAsync() { var client = new WasabiClient(BackendHttpClient); var uptodate = await client.CheckUpdatesAsync(CancellationToken.None); Assert.True(uptodate.BackendCompatible); Assert.True(uptodate.ClientUpToDate); }
public async Task GetExchangeRatesAsync(NetworkType networkType) { using (var client = new WasabiClient(LiveServerTestsFixture.UriMappings[networkType])) { var exchangeRates = await client.GetExchangeRatesAsync(); Assert.True(exchangeRates.NotNullAndNotEmpty()); } }
public async Task GetFeesAsync(NetworkType networkType) { using (var client = new WasabiClient(LiveServerTestsFixture.UriMappings[networkType])) { var feeEstimationPairs = await client.GetFeesAsync(1000); Assert.True(feeEstimationPairs.NotNullAndNotEmpty()); } }
public async Task GetExchangeRateAsync(NetworkType networkType) // xunit wtf: If this function is called GetExchangeRatesAsync, it'll stuck on 1 CPU VMs (Manjuro, Fedora) { using var torHttpClient = MakeTorHttpClient(networkType); var client = new WasabiClient(torHttpClient); var exchangeRates = await client.GetExchangeRatesAsync(); Assert.True(exchangeRates.NotNullAndNotEmpty()); }
/// <summary> /// Tries to perform mempool cleanup with the help of the backend. /// </summary> public async Task <bool> TryPerformMempoolCleanupAsync(Func <Uri> destAction, EndPoint torSocks) { // If already cleaning, then no need to run it that often. if (Interlocked.CompareExchange(ref _cleanupInProcess, 1, 0) == 1) { return(false); } // This function is designed to prevent forever growing mempool. try { // No need for locking when accessing Count. if (ProcessedTransactionHashes.Count == 0) { // There's nothing to cleanup. return(true); } Logger.LogInfo("Start cleaning out mempool..."); using (var client = new WasabiClient(destAction, torSocks)) { var compactness = 10; var allMempoolHashes = await client.GetMempoolHashesAsync(compactness); lock (ProcessedLock) { int removedTxCount = ProcessedTransactionHashes.RemoveWhere(x => !allMempoolHashes.Contains(x.ToString().Substring(0, compactness))); Logger.LogInfo($"{removedTxCount} transactions were cleaned from mempool."); } } // Display warning if total receives would be reached by duplicated receives. // Also reset the benchmarking. var totalReceived = Interlocked.Exchange(ref _totalReceives, 0); var duplicatedReceived = Interlocked.Exchange(ref _duplicatedReceives, 0); if (duplicatedReceived >= totalReceived) { // Note that the worst case scenario is not duplicatedReceived == totalReceived, but duplicatedReceived == (number of peers) * totalReceived. // It's just duplicatedReceived == totalReceived is maximum what we want to tolerate. // By turning off Tor, we can notice that the ratio is much better, so this mainly depends on the internet speed. Logger.LogWarning($"Too many duplicated mempool transactions are downloaded.\n{nameof(duplicatedReceived)} : {duplicatedReceived}\n{nameof(totalReceived)} : {totalReceived}"); } return(true); } catch (Exception ex) { Logger.LogWarning(ex); } finally { Interlocked.Exchange(ref _cleanupInProcess, 0); } return(false); }
private long _blockRequests; // There are priority requests in queue. public WasabiSynchronizer(Network network, BitcoinStore bitcoinStore, Func <Uri> baseUriAction, EndPoint torSocks5EndPoint) { WasabiClient = new WasabiClient(baseUriAction, torSocks5EndPoint); Network = Guard.NotNull(nameof(network), network); LastResponse = null; _running = 0; Cancel = new CancellationTokenSource(); BitcoinStore = Guard.NotNull(nameof(bitcoinStore), bitcoinStore); }
public async Task GetFiltersAsync(NetworkType networkType) { using var client = new WasabiClient(LiveServerTestsFixture.UriMappings[networkType], Global.Instance.TorSocks5Endpoint); var filterModel = StartingFilters.GetStartingFilter(Network.GetNetwork(networkType.ToString())); FiltersResponse filtersResponse = await client.GetFiltersAsync(filterModel.Header.BlockHash, 2); Assert.NotNull(filtersResponse); Assert.True(filtersResponse.Filters.Count() == 2); }
public async Task GetVersionsTestsAsync(NetworkType networkType) { using var client = new WasabiClient(LiveServerTestsFixture.UriMappings[networkType], Global.Instance.TorSocks5Endpoint); var versions = await client.GetVersionsAsync(CancellationToken.None); Assert.InRange(versions.ClientVersion, new Version(1, 1, 10), new Version(1, 2)); Assert.InRange(versions.ClientVersion, new Version(1, 1, 10), WalletWasabi.Helpers.Constants.ClientVersion); Assert.Equal(3, versions.BackendMajorVersion); Assert.Equal(new Version(2, 0), versions.LegalDocumentsVersion); }
public async Task GetFiltersAsync(NetworkType networkType) { using (var client = new WasabiClient(LiveServerTestsFixture.UriMappings[networkType])) { var filterModel = IndexDownloader.GetStartingFilter(Network.GetNetwork(networkType.ToString())); FiltersResponse filtersResponse = await client.GetFiltersAsync(filterModel.BlockHash, 2); Assert.NotNull(filtersResponse); Assert.True(filtersResponse.Filters.Count() == 2); } }
public async Task GetVersionsTestsAsync(NetworkType networkType) { using var torHttpClient = MakeTorHttpClient(networkType); var client = new WasabiClient(torHttpClient); var versions = await client.GetVersionsAsync(CancellationToken.None); Assert.InRange(versions.ClientVersion, new Version(1, 1, 10), new Version(1, 2)); Assert.InRange(versions.ClientVersion, new Version(1, 1, 10), WalletWasabi.Helpers.Constants.ClientVersion); Assert.Equal(4, versions.BackendMajorVersion); Assert.Equal(new Version(2, 0), versions.LegalDocumentsVersion); }
public async Task GetFiltersAsync(NetworkType networkType) { Network network = (networkType == NetworkType.Mainnet) ? Network.Main : Network.TestNet; using var client = new WasabiClient(LiveServerTestsFixture.UriMappings[networkType], Common.TorSocks5Endpoint); var filterModel = StartingFilters.GetStartingFilter(network); FiltersResponse filtersResponse = await client.GetFiltersAsync(filterModel.Header.BlockHash, 2); Assert.NotNull(filtersResponse); Assert.True(filtersResponse.Filters.Count() == 2); }
public async Task StopAsync() { if (IsRunning) { Interlocked.Exchange(ref _running, 2); } while (IsStopping) { await Task.Delay(50); } WasabiClient?.Dispose(); }
public async Task GetLegalDocumentsTestsAsync(NetworkType networkType) { using var client = new WasabiClient(LiveServerTestsFixture.UriMappings[networkType], Global.Instance.TorSocks5Endpoint); var content = await client.GetLegalDocumentsAsync(CancellationToken.None); var lines = content.Split('\n', StringSplitOptions.RemoveEmptyEntries); Assert.Equal("Last Updated: 2020-04-05", lines[0]); var lineCount = lines.Length; Assert.InRange(lineCount, 100, 1000); }
public async Task GetFiltersAsync(NetworkType networkType) { Network network = (networkType == NetworkType.Mainnet) ? Network.Main : Network.TestNet; using var torHttpClient = MakeTorHttpClient(networkType); var client = new WasabiClient(torHttpClient); var filterModel = StartingFilters.GetStartingFilter(network); FiltersResponse?filtersResponse = await client.GetFiltersAsync(filterModel.Header.BlockHash, 2); Assert.NotNull(filtersResponse); Assert.True(filtersResponse !.Filters.Count() == 2); }
public async Task GetLegalDocumentsTestsAsync(NetworkType networkType) { using var torHttpClient = MakeTorHttpClient(networkType); var client = new WasabiClient(torHttpClient); var content = await client.GetLegalDocumentsAsync(CancellationToken.None); var lines = content.Split('\n', StringSplitOptions.RemoveEmptyEntries); Assert.Equal("Last Updated: 2020-04-05", lines[0]); var lineCount = lines.Length; Assert.InRange(lineCount, 100, 1000); }
/// <summary> /// Tries to perform mempool cleanup with the help of the backend. /// </summary> public async Task <bool> TryPerformMempoolCleanupAsync(Func <Uri> destAction, IPEndPoint torSocks) { // If already cleaning, then no need to run it that often. if (Interlocked.CompareExchange(ref _cleanupInProcess, 1, 0) == 1) { return(false); } // This function is designed to prevent forever growing mempool. try { if (!TransactionHashes.Any()) { return(true); // There's nothing to cleanup. } Logger.LogInfo <MempoolService>("Start cleaning out mempool..."); using (var client = new WasabiClient(destAction, torSocks)) { var compactness = 10; var allMempoolHashes = await client.GetMempoolHashesAsync(compactness); var toRemove = TransactionHashes.Where(x => !allMempoolHashes.Contains(x.ToString().Substring(0, compactness))); int removedTxCount = 0; foreach (uint256 tx in toRemove) { if (TransactionHashes.TryRemove(tx)) { removedTxCount++; } } Logger.LogInfo <MempoolService>($"{removedTxCount} transactions were cleaned from mempool."); } return(true); } catch (Exception ex) { Logger.LogWarning <MempoolService>(ex); } finally { Interlocked.Exchange(ref _cleanupInProcess, 0); } return(false); }
public async Task StaticClient() { NullNetworkDriver driver = new NullNetworkDriver(); WasabiConfig config = new WasabiConfig(); config.Credentials = new StringAccessKey("ExampleKeyId00000000", "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY"); config.Region = WasabiRegion.EuCentral1; using WasabiClient client = new WasabiClient(config, driver); await client.GetObjectAsync("testbucket", "GetObjectAsync").ConfigureAwait(false); Assert.Equal("https://testbucket.s3.eu-central-1.wasabisys.com/GetObjectAsync", driver.LastUrl); }
private async Task LoadDummyMempoolAsync() { if (BitcoinStore.TransactionStore.MempoolStore.IsEmpty()) { return; } // Only clean the mempool if we're fully synchronized. if (BitcoinStore.SmartHeaderChain.HashesLeft == 0) { try { using var client = new WasabiClient(Synchronizer.WasabiClient.TorClient.DestinationUriAction, Synchronizer.WasabiClient.TorClient.TorSocks5EndPoint); var compactness = 10; var mempoolHashes = await client.GetMempoolHashesAsync(compactness); var txsToProcess = new List <SmartTransaction>(); foreach (var tx in BitcoinStore.TransactionStore.MempoolStore.GetTransactions()) { uint256 hash = tx.GetHash(); if (mempoolHashes.Contains(hash.ToString().Substring(0, compactness))) { txsToProcess.Add(tx); Logger.LogInfo($"Transaction was successfully tested against the backend's mempool hashes: {hash}."); } else { BitcoinStore.TransactionStore.MempoolStore.TryRemove(tx.GetHash(), out _); } } TransactionProcessor.Process(txsToProcess); } catch (Exception ex) { // When there's a connection failure do not clean the transactions, add them to processing. TransactionProcessor.Process(BitcoinStore.TransactionStore.MempoolStore.GetTransactions()); Logger.LogWarning(ex); } } else { TransactionProcessor.Process(BitcoinStore.TransactionStore.MempoolStore.GetTransactions()); } }
public async Task CheckUpdatesTestsAsync(NetworkType networkType) { using var client = new WasabiClient(LiveServerTestsFixture.UriMappings[networkType], Global.Instance.TorSocks5Endpoint); var updateStatus = await client.CheckUpdatesAsync(CancellationToken.None); var expectedVersion = new Version(2, 0); Assert.Equal(new UpdateStatus(true, true, expectedVersion), updateStatus); Assert.True(updateStatus.BackendCompatible); Assert.True(updateStatus.ClientUpToDate); Assert.Equal(expectedVersion, updateStatus.LegalDocumentsVersion); var versions = await client.GetVersionsAsync(CancellationToken.None); Assert.Equal(versions.LegalDocumentsVersion, updateStatus.LegalDocumentsVersion); }
public IndexDownloader(Network network, string indexFilePath, Uri indexHostUri, IPEndPoint torSocks5EndPoint = null) { Network = Guard.NotNull(nameof(network), network); WasabiClient = new WasabiClient(indexHostUri, torSocks5EndPoint); IndexFilePath = Guard.NotNullOrEmptyOrWhitespace(nameof(indexFilePath), indexFilePath); Index = new List <FilterModel>(); IndexLock = new AsyncLock(); _running = 0; var indexDir = Path.GetDirectoryName(IndexFilePath); if (!string.IsNullOrEmpty(indexDir)) { Directory.CreateDirectory(indexDir); } if (File.Exists(IndexFilePath)) { if (Network == Network.RegTest) { File.Delete(IndexFilePath); // RegTest is not a global ledger, better to delete it. Index.Add(StartingFilter); File.WriteAllLines(IndexFilePath, Index.Select(x => x.ToLine())); } else { var height = StartingHeight; foreach (var line in File.ReadAllLines(IndexFilePath)) { var filter = FilterModel.FromLine(line, height); height++; Index.Add(filter); } } } else { Index.Add(StartingFilter); File.WriteAllLines(IndexFilePath, Index.Select(x => x.ToLine())); } }
public async Task GetTransactionsAsync(NetworkType networkType) { using var client = new WasabiClient(LiveServerTestsFixture.UriMappings[networkType], Global.Instance.TorSocks5Endpoint); var randomTxIds = Enumerable.Range(0, 20).Select(_ => RandomUtils.GetUInt256()); var network = networkType == NetworkType.Mainnet ? Network.Main : Network.TestNet; var ex = await Assert.ThrowsAsync <HttpRequestException>(async() => await client.GetTransactionsAsync(network, randomTxIds.Take(4), CancellationToken.None)); Assert.Equal("Bad Request\nNo such mempool or blockchain transaction. Use gettransaction for wallet transactions.", ex.Message); var mempoolTxIds = await client.GetMempoolHashesAsync(CancellationToken.None); randomTxIds = Enumerable.Range(0, 5).Select(_ => mempoolTxIds.RandomElement()).Distinct().ToArray(); var txs = await client.GetTransactionsAsync(network, randomTxIds, CancellationToken.None); var returnedTxIds = txs.Select(tx => tx.GetHash()); Assert.Equal(returnedTxIds.OrderBy(x => x).ToArray(), randomTxIds.OrderBy(x => x).ToArray()); }
public async Task CheckUpdatesTestsAsync(NetworkType networkType) { using var torHttpClient = MakeTorHttpClient(networkType); var client = new WasabiClient(torHttpClient); var updateStatus = await client.CheckUpdatesAsync(CancellationToken.None); var expectedVersion = new Version(2, 0); ushort backendVersion = 4; Assert.Equal(new UpdateStatus(true, true, expectedVersion, backendVersion), updateStatus); Assert.True(updateStatus.BackendCompatible); Assert.True(updateStatus.ClientUpToDate); Assert.Equal(expectedVersion, updateStatus.LegalDocumentsVersion); Assert.Equal(backendVersion, updateStatus.CurrentBackendMajorVersion); var versions = await client.GetVersionsAsync(CancellationToken.None); Assert.Equal(versions.LegalDocumentsVersion, updateStatus.LegalDocumentsVersion); }
private static async Task AssertFiltersInitializedAsync(RegTestFixture regTestFixture, Backend.Global global) { var firstHash = await global.RpcClient.GetBlockHashAsync(0); while (true) { using var client = new WasabiClient(new Uri(regTestFixture.BackendEndPoint), null); FiltersResponse filtersResponse = await client.GetFiltersAsync(firstHash, 1000); Assert.NotNull(filtersResponse); var filterCount = filtersResponse.Filters.Count(); if (filterCount >= 101) { break; } else { await Task.Delay(100); } } }