Make transaction processor lock private
MODIFY
WalletWasabi/Blockchain/TransactionBroadcasting/TransactionBroadcaster.cs
WalletWasabi/Blockchain/TransactionBroadcasting/TransactionBroadcaster.cs
@@ -136,11 +136,10 @@ namespace WalletWasabi.Blockchain.TransactionBroadcasting
private void BelieveTransaction(SmartTransaction transaction)
{
lock (WalletServicesLock)
- lock (TransactionProcessor.Lock)
{
foreach (var walletService in AliveWalletServices)
{
- walletService.TransactionProcessor.Process(new SmartTransaction(transaction.Transaction, Height.Mempool));
+ walletService.TransactionProcessor.Process(transaction);
}
}
}

MODIFY
WalletWasabi/Blockchain/TransactionProcessing/TransactionProcessor.cs
WalletWasabi/Blockchain/TransactionProcessing/TransactionProcessor.cs
@@ -12,7 +12,7 @@ namespace WalletWasabi.Blockchain.TransactionProcessing
{
public class TransactionProcessor
{
- public static object Lock { get; } = new object();
+ private static object Lock { get; } = new object();
public AllTransactionStore TransactionStore { get; }
public KeyManager KeyManager { get; }
@@ -45,7 +45,28 @@ namespace WalletWasabi.Blockchain.TransactionProcessing
Coins = new CoinsRegistry(privacyLevelThreshold);
}
+ public IEnumerable<bool> Process(IEnumerable<SmartTransaction> txs)
+ {
+ lock (Lock)
+ {
+ var ret = new List<bool>();
+ foreach (var tx in txs)
+ {
+ ret.Add(ProcessNoLock(tx));
+ }
+ return ret;
+ }
+ }
+
public bool Process(SmartTransaction tx)
+ {
+ lock (Lock)
+ {
+ return ProcessNoLock(tx);
+ }
+ }
+
+ private bool ProcessNoLock(SmartTransaction tx)
{
var walletRelevant = false;
// We do not care about non-witness transactions for other than mempool cleanup.

MODIFY
WalletWasabi/CoinJoin/Client/CoinJoinProcessor.cs
WalletWasabi/CoinJoin/Client/CoinJoinProcessor.cs
@@ -67,7 +67,7 @@ namespace WalletWasabi.CoinJoin.Client
var unconfirmedCoinJoins = await client.GetTransactionsAsync(Synchronizer.Network, txsNotKnownByAWalletService, CancellationToken.None).ConfigureAwait(false);
- foreach (Transaction tx in unconfirmedCoinJoins)
+ foreach (var tx in unconfirmedCoinJoins.Select(x => new SmartTransaction(x, Height.Mempool)))
{
if (RpcClient is null
|| await TryBroadcastTransactionWithRpcAsync(tx).ConfigureAwait(false)
@@ -93,25 +93,24 @@ namespace WalletWasabi.CoinJoin.Client
}
}
- private void BelieveTransaction(Transaction transaction)
+ private void BelieveTransaction(SmartTransaction transaction)
{
lock (WalletServicesLock)
- lock (TransactionProcessor.Lock)
{
foreach (var pair in AliveWalletServices.Where(x => !x.Value.Contains(transaction.GetHash())))
{
var walletService = pair.Key;
pair.Value.Add(transaction.GetHash());
- walletService.TransactionProcessor.Process(new SmartTransaction(transaction, Height.Mempool));
+ walletService.TransactionProcessor.Process(transaction);
}
}
}
- private async Task<bool> TryBroadcastTransactionWithRpcAsync(Transaction transaction)
+ private async Task<bool> TryBroadcastTransactionWithRpcAsync(SmartTransaction transaction)
{
try
{
- await RpcClient.SendRawTransactionAsync(transaction).ConfigureAwait(false);
+ await RpcClient.SendRawTransactionAsync(transaction.Transaction).ConfigureAwait(false);
Logger.LogInfo($"Transaction is successfully broadcasted with RPC: {transaction.GetHash()}.");
return true;

MODIFY
WalletWasabi/Services/WalletService.cs
WalletWasabi/Services/WalletService.cs
@@ -175,12 +175,9 @@ namespace WalletWasabi.Services
private void Mempool_TransactionReceived(object sender, SmartTransaction tx)
{
try
- {
- lock (TransactionProcessor.Lock)
{
TransactionProcessor.Process(tx);
}
- }
catch (Exception ex)
{
Logger.LogWarning(ex);
@@ -268,13 +265,8 @@ namespace WalletWasabi.Services
{
KeyManager.AssertNetworkOrClearBlockState(Network);
Height bestKeyManagerHeight = KeyManager.GetBestHeight();
- lock (TransactionProcessor.Lock)
- {
- foreach (var tx in BitcoinStore.TransactionStore.ConfirmedStore.GetTransactions().TakeWhile(x => x.Height <= bestKeyManagerHeight))
- {
- TransactionProcessor.Process(tx);
- }
- }
+
+ TransactionProcessor.Process(BitcoinStore.TransactionStore.ConfirmedStore.GetTransactions().TakeWhile(x => x.Height <= bestKeyManagerHeight));
// Go through the filters and queue to download the matches.
await BitcoinStore.IndexStore.ForeachFiltersAsync(async (filterModel) =>
@@ -301,15 +293,13 @@ namespace WalletWasabi.Services
var mempoolHashes = await client.GetMempoolHashesAsync(compactness);
- lock (TransactionProcessor.Lock)
- {
+ 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)))
{
- TransactionProcessor.Process(tx);
-
+ txsToProcess.Add(tx);
Logger.LogInfo($"Transaction was successfully tested against the backend's mempool hashes: {hash}.");
}
else
@@ -317,18 +307,13 @@ namespace WalletWasabi.Services
BitcoinStore.TransactionStore.MempoolStore.TryRemove(tx.GetHash(), out _);
}
}
- }
+
+ TransactionProcessor.Process(txsToProcess);
}
catch (Exception ex)
- {
- lock (TransactionProcessor.Lock)
{
// When there's a connection failure do not clean the transactions, add them to processing.
- foreach (var tx in BitcoinStore.TransactionStore.MempoolStore.GetTransactions())
- {
- TransactionProcessor.Process(tx);
- }
- }
+ TransactionProcessor.Process(BitcoinStore.TransactionStore.MempoolStore.GetTransactions());
Logger.LogWarning(ex);
}
@@ -345,16 +330,14 @@ namespace WalletWasabi.Services
Block currentBlock = await FetchBlockAsync(filterModel.Header.BlockHash, cancel); // Wait until not downloaded.
var height = new Height(filterModel.Header.Height);
- lock (TransactionProcessor.Lock)
- {
+ var txsToProcess = new List<SmartTransaction>();
for (int i = 0; i < currentBlock.Transactions.Count; i++)
{
Transaction tx = currentBlock.Transactions[i];
- TransactionProcessor.Process(new SmartTransaction(tx, height, currentBlock.GetHash(), i, firstSeen: currentBlock.Header.BlockTime));
+ txsToProcess.Add(new SmartTransaction(tx, height, currentBlock.GetHash(), i, firstSeen: currentBlock.Header.BlockTime));
}
-
+ TransactionProcessor.Process(txsToProcess);
KeyManager.SetBestHeight(height);
- }
NewBlockProcessed?.Invoke(this, currentBlock);
}

Make transaction processor lock private