Skip coinjoins if we have more coins later

This commit is contained in:
Kukks
2024-01-09 09:24:33 +01:00
parent 62c6054927
commit d27a31ee8e
4 changed files with 38 additions and 12 deletions

View File

@@ -27,12 +27,14 @@ public class BTCPayCoinjoinCoinSelector : IRoundCoinSelector
_wallet = wallet; _wallet = wallet;
} }
public async Task<ImmutableList<SmartCoin>> SelectCoinsAsync(IEnumerable<SmartCoin> coinCandidates, public async Task<ImmutableList<SmartCoin>> SelectCoinsAsync(
(IEnumerable<SmartCoin> Candidates, IEnumerable<SmartCoin> Ineligible) coinCandidates,
UtxoSelectionParameters utxoSelectionParameters, UtxoSelectionParameters utxoSelectionParameters,
Money liquidityClue, SecureRandom secureRandom) Money liquidityClue, SecureRandom secureRandom)
{ {
coinCandidates = SmartCoin[] FilterCoinsMore(IEnumerable<SmartCoin> coins)
coinCandidates {
return coins
.Where(coin => utxoSelectionParameters.AllowedInputScriptTypes.Contains(coin.ScriptType)) .Where(coin => utxoSelectionParameters.AllowedInputScriptTypes.Contains(coin.ScriptType))
.Where(coin => utxoSelectionParameters.AllowedInputAmounts.Contains(coin.Amount)) .Where(coin => utxoSelectionParameters.AllowedInputAmounts.Contains(coin.Amount))
.Where(coin => .Where(coin =>
@@ -65,11 +67,18 @@ public class BTCPayCoinjoinCoinSelector : IRoundCoinSelector
return false; return false;
}); }).ToArray();
}
var candidates =
FilterCoinsMore(coinCandidates.Candidates);
var ineligibleCoins =
FilterCoinsMore(coinCandidates.Ineligible);
var payments = var payments =
_wallet.BatchPayments (_wallet.BatchPayments
? await _wallet.DestinationProvider.GetPendingPaymentsAsync(utxoSelectionParameters) ? await _wallet.DestinationProvider.GetPendingPaymentsAsync(utxoSelectionParameters)
: Array.Empty<PendingPayment>(); : Array.Empty<PendingPayment>()).ToArray();
var maxPerType = new Dictionary<AnonsetType, int>(); var maxPerType = new Dictionary<AnonsetType, int>();
@@ -94,13 +103,13 @@ public class BTCPayCoinjoinCoinSelector : IRoundCoinSelector
ConsolidationModeType.Always => true, ConsolidationModeType.Always => true,
ConsolidationModeType.Never => false, ConsolidationModeType.Never => false,
ConsolidationModeType.WhenLowFee => isLowFee, ConsolidationModeType.WhenLowFee => isLowFee,
ConsolidationModeType.WhenLowFeeAndManyUTXO => isLowFee && coinCandidates.Count() > BTCPayWallet.HighAmountOfCoins, ConsolidationModeType.WhenLowFeeAndManyUTXO => isLowFee && candidates.Count() > BTCPayWallet.HighAmountOfCoins,
_ => throw new ArgumentOutOfRangeException() _ => throw new ArgumentOutOfRangeException()
}; };
Dictionary<AnonsetType, int> idealMinimumPerType = new Dictionary<AnonsetType, int>() Dictionary<AnonsetType, int> idealMinimumPerType = new Dictionary<AnonsetType, int>()
{{AnonsetType.Red, 1}, {AnonsetType.Orange, 1}, {AnonsetType.Green, 1}}; {{AnonsetType.Red, 1}, {AnonsetType.Orange, 1}, {AnonsetType.Green, 1}};
var solution = await SelectCoinsInternal(utxoSelectionParameters, coinCandidates, payments, var solution = await SelectCoinsInternal(utxoSelectionParameters, candidates, ineligibleCoins,payments,
Random.Shared.Next(10, 31), Random.Shared.Next(10, 31),
maxPerType, maxPerType,
idealMinimumPerType, idealMinimumPerType,
@@ -124,7 +133,7 @@ public class BTCPayCoinjoinCoinSelector : IRoundCoinSelector
} }
private async Task<SubsetSolution> SelectCoinsInternal(UtxoSelectionParameters utxoSelectionParameters, private async Task<SubsetSolution> SelectCoinsInternal(UtxoSelectionParameters utxoSelectionParameters,
IEnumerable<SmartCoin> coins, IEnumerable<PendingPayment> pendingPayments, IEnumerable<SmartCoin> coins,IEnumerable<SmartCoin> ineligibleCoins, IEnumerable<PendingPayment> pendingPayments,
int maxCoins, int maxCoins,
Dictionary<AnonsetType, int> maxPerType, Dictionary<AnonsetType, int> idealMinimumPerType, Dictionary<AnonsetType, int> maxPerType, Dictionary<AnonsetType, int> idealMinimumPerType,
bool consolidationMode, Money liquidityClue, SecureRandom random) bool consolidationMode, Money liquidityClue, SecureRandom random)
@@ -150,6 +159,23 @@ public class BTCPayCoinjoinCoinSelector : IRoundCoinSelector
consolidationMode = true; consolidationMode = true;
} }
solution.ConsolidationMode = consolidationMode; solution.ConsolidationMode = consolidationMode;
if(consolidationMode && coins.Count() < 8 && !coinjoiningOnlyForPayments && ineligibleCoins.Any())
{
//if we're in consolidation mode, and there are coins not eligible for a reason that will be ok in the near future, we should try to wait for them to become eligible instead of entering multiple coinjoins, which costs more.
// why are they ineligible? banned if not too far in the future is ok, unconfrmed as well
if (ineligibleCoins.Any(coin => !coin.Confirmed))
{
// if there are unconfirmed coins, we should wait for them to confirm, but since we cant determine if they will be unconfirmed for a long time,. let's play a random chance game: the more coins we have towards the 8 coin goal, the bigger the chance we proceed with the coinjoin
var rand = Random.Shared.Next(1, 101);
var chance = (coins.Count()/8) * 100;
_wallet.LogDebug($"coin selection: consolidation mode, and there are coins not eligible for a reason that will be ok in the near future, we should try to wait for them to become eligible instead of entering multiple coinjoins, which costs more. random chance to proceed: {chance} > {rand} (random 0-100) continue: {chance > rand}");
if (chance > rand)
{
return solution;
}
}
}
if (fullyPrivate && !coinjoiningOnlyForPayments ) if (fullyPrivate && !coinjoiningOnlyForPayments )
{ {
var rand = Random.Shared.Next(1, 1001); var rand = Random.Shared.Next(1, 1001);

View File

@@ -13,7 +13,7 @@
<PropertyGroup> <PropertyGroup>
<Product>Coinjoin</Product> <Product>Coinjoin</Product>
<Description>Allows you to integrate your btcpayserver store with coinjoins.</Description> <Description>Allows you to integrate your btcpayserver store with coinjoins.</Description>
<Version>1.0.68</Version> <Version>1.0.69</Version>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup> </PropertyGroup>

View File

@@ -106,7 +106,7 @@ public class BTCPayWallet : IWallet, IDestinationProvider
}; };
if(LastLogs.FirstOrDefault().message != logMessage) if(LastLogs.FirstOrDefault().message != logMessage)
LastLogs.Insert(0, (DateTimeOffset.Now, ll, logMessage) ); LastLogs.Insert(0, (DateTimeOffset.Now, ll, logMessage) );
if (LastLogs.Count >= 100) if (LastLogs.Count >= 500)
LastLogs.RemoveLast(); LastLogs.RemoveLast();
_logger.Log(ll, logMessage, callerFilePath, callerMemberName, callerLineNumber); _logger.Log(ll, logMessage, callerFilePath, callerMemberName, callerLineNumber);