/// <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); }
/// <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); }
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 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()); }