Initialize liquidity clue
MODIFY
WalletWasabi/WabiSabi/Client/CoinJoinClient.cs
WalletWasabi/WabiSabi/Client/CoinJoinClient.cs
@@ -46,7 +46,8 @@ public class CoinJoinClient
bool consolidationMode = false,
bool redCoinIsolation = false,
TimeSpan feeRateMedianTimeFrame = default,
- TimeSpan doNotRegisterInLastMinuteTimeLimit = default)
+ TimeSpan doNotRegisterInLastMinuteTimeLimit = default,
+ Money? liquidityClue = null)
{
HttpClientFactory = httpClientFactory;
KeyChain = keyChain;
@@ -58,6 +59,10 @@ public class CoinJoinClient
FeeRateMedianTimeFrame = feeRateMedianTimeFrame;
SecureRandom = new SecureRandom();
DoNotRegisterInLastMinuteTimeLimit = doNotRegisterInLastMinuteTimeLimit;
+ lock (LiquidityClueLock)
+ {
+ LiquidityClue ??= liquidityClue;
+ }
}
public event EventHandler<CoinJoinProgressEventArgs>? CoinJoinClientProgress;
@@ -76,6 +81,14 @@ public class CoinJoinClient
private static Money? LiquidityClue { get; set; }
private static object LiquidityClueLock { get; } = new object();
+ public static Money? GetLiquidityClue()
+ {
+ lock (LiquidityClueLock)
+ {
+ return LiquidityClue;
+ }
+ }
+
private async Task<RoundState> WaitForRoundAsync(uint256 excludeRound, CancellationToken token)
{
CoinJoinClientProgress.SafeInvoke(this, new WaitingForRound());
@@ -247,15 +260,7 @@ public class CoinJoinClient
lock (LiquidityClueLock)
{
- var secondLargestDenomOutput = unsignedCoinJoin.Outputs
- .Where(x =>
- BlockchainAnalyzer.StdDenoms.Contains(x.Value.Satoshi) // We only care about denom outputs as those can be considered reasonably mixed.
- && !outputTxOuts.Any(y => y.ScriptPubKey == x.ScriptPubKey && y.Value == x.Value)) // We only care about outputs those aren't ours.
- .Select(x => x.Value)
- .Distinct()
- .OrderByDescending(x => x)
- .Skip(1)
- .FirstOrDefault();
+ Money? secondLargestDenomOutput = CalculateLiquidityClue(unsignedCoinJoin, outputTxOuts);
// Dismiss pleb round.
// If it's close to the max suggested amount then we shouldn't set it as the round is likely a pleb round.
@@ -289,6 +294,20 @@ public class CoinJoinClient
}
}
+ public static Money? CalculateLiquidityClue(Transaction coinjoin, IEnumerable<TxOut>? ownTxOuts = null)
+ {
+ var secondLargestDenomOutput = coinjoin.Outputs
+ .Where(x =>
+ BlockchainAnalyzer.StdDenoms.Contains(x.Value.Satoshi) // We only care about denom outputs as those can be considered reasonably mixed.
+ && !ownTxOuts?.Any(y => y.ScriptPubKey == x.ScriptPubKey && y.Value == x.Value) is true) // We only care about outputs those aren't ours.
+ .Select(x => x.Value)
+ .Distinct()
+ .OrderByDescending(x => x)
+ .Skip(1)
+ .FirstOrDefault();
+ return secondLargestDenomOutput;
+ }
+
private async Task<ImmutableArray<(AliceClient AliceClient, PersonCircuit PersonCircuit)>> CreateRegisterAndConfirmCoinsAsync(IEnumerable<SmartCoin> smartCoins, RoundState roundState, CancellationToken cancel)
{
int eventInvokedAlready = 0;

MODIFY
WalletWasabi/WabiSabi/Client/CoinJoinTrackerFactory.cs
WalletWasabi/WabiSabi/Client/CoinJoinTrackerFactory.cs
+using NBitcoin;
using System.Collections.Generic;
+using System.Linq;
using System.Threading;
using WalletWasabi.Blockchain.TransactionOutputs;
+using WalletWasabi.Extensions;
using WalletWasabi.WabiSabi.Client.RoundStateAwaiters;
using WalletWasabi.Wallets;
using WalletWasabi.WebClients.Wasabi;
@@ -25,6 +28,16 @@ public class CoinJoinTrackerFactory
public CoinJoinTracker CreateAndStart(Wallet wallet, IEnumerable<SmartCoin> coinCandidates, bool restartAutomatically, bool overridePlebStop)
{
+ Money? liquidityClue = null;
+ if (CoinJoinClient.GetLiquidityClue() is not null)
+ {
+ var lastCoinjoin = wallet.TransactionProcessor.TransactionStore.GetTransactions().OrderByBlockchain().LastOrDefault(x => x.IsOwnCoinjoin());
+ if (lastCoinjoin is not null)
+ {
+ liquidityClue = CoinJoinClient.CalculateLiquidityClue(lastCoinjoin.Transaction, lastCoinjoin.WalletOutputs.Select(x => x.TxOut));
+ }
+ }
+
var coinJoinClient = new CoinJoinClient(
HttpClientFactory,
new KeyChain(wallet.KeyManager, wallet.Kitchen),
@@ -34,7 +47,8 @@ public class CoinJoinTrackerFactory
consolidationMode: false,
redCoinIsolation: wallet.KeyManager.RedCoinIsolation,
feeRateMedianTimeFrame: TimeSpan.FromHours(wallet.KeyManager.FeeRateMedianTimeFrameHours),
- doNotRegisterInLastMinuteTimeLimit: TimeSpan.FromMinutes(1));
+ doNotRegisterInLastMinuteTimeLimit: TimeSpan.FromMinutes(1),
+ liquidityClue: liquidityClue);
return new CoinJoinTracker(wallet, coinJoinClient, coinCandidates, restartAutomatically, overridePlebStop, CancellationToken);
}

Initialize liquidity clue