This commit is contained in:
Kukks
2024-02-08 14:14:09 +01:00
parent bc98568afa
commit aae93286de
4 changed files with 39 additions and 14 deletions

View File

@@ -27,7 +27,7 @@ public class BTCPayCoinjoinCoinSelector : IRoundCoinSelector
_wallet = wallet; _wallet = wallet;
} }
public async Task<ImmutableList<SmartCoin>> SelectCoinsAsync( public async Task<(ImmutableList<SmartCoin> selected, Func<IEnumerable<SmartCoin>, Task<bool>> acceptableSigned)> SelectCoinsAsync(
(IEnumerable<SmartCoin> Candidates, IEnumerable<SmartCoin> Ineligible) coinCandidates, (IEnumerable<SmartCoin> Candidates, IEnumerable<SmartCoin> Ineligible) coinCandidates,
UtxoSelectionParameters utxoSelectionParameters, UtxoSelectionParameters utxoSelectionParameters,
Money liquidityClue, SecureRandom secureRandom) Money liquidityClue, SecureRandom secureRandom)
@@ -82,11 +82,11 @@ public class BTCPayCoinjoinCoinSelector : IRoundCoinSelector
var maxPerType = new Dictionary<AnonsetType, int>(); var maxPerType = new Dictionary<AnonsetType, int>();
var attemptingTobeParanoid = payments.Any() && _wallet.WabisabiStoreSettings.ParanoidPayments; var attemptingTobeParanoidWhenDoingPayments = payments.Any() && _wallet.WabisabiStoreSettings.ParanoidPayments;
var attemptingToMixToOtherWallet = string.IsNullOrEmpty(_wallet.WabisabiStoreSettings.MixToOtherWallet); var attemptingToMixToOtherWallet = string.IsNullOrEmpty(_wallet.WabisabiStoreSettings.MixToOtherWallet);
selectCoins: selectCoins:
maxPerType.Clear(); maxPerType.Clear();
if (attemptingTobeParanoid || attemptingToMixToOtherWallet) if (attemptingTobeParanoidWhenDoingPayments || attemptingToMixToOtherWallet)
{ {
maxPerType.Add(AnonsetType.Red,0); maxPerType.Add(AnonsetType.Red,0);
maxPerType.Add(AnonsetType.Orange,0); maxPerType.Add(AnonsetType.Orange,0);
@@ -110,14 +110,14 @@ public class BTCPayCoinjoinCoinSelector : IRoundCoinSelector
{{AnonsetType.Red, 1}, {AnonsetType.Orange, 1}, {AnonsetType.Green, 1}}; {{AnonsetType.Red, 1}, {AnonsetType.Orange, 1}, {AnonsetType.Green, 1}};
var solution = await SelectCoinsInternal(utxoSelectionParameters, candidates, ineligibleCoins,payments, var solution = await SelectCoinsInternal(utxoSelectionParameters, candidates, ineligibleCoins,payments,
Random.Shared.Next(10, 31), Random.Shared.Next(20, 31),
maxPerType, maxPerType,
idealMinimumPerType, idealMinimumPerType,
consolidationMode, liquidityClue, secureRandom); consolidationMode, liquidityClue, secureRandom);
if (attemptingTobeParanoid && !solution.HandledPayments.Any()) if (attemptingTobeParanoidWhenDoingPayments && !solution.HandledPayments.Any())
{ {
attemptingTobeParanoid = false; attemptingTobeParanoidWhenDoingPayments = false;
payments = Array.Empty<PendingPayment>(); payments = Array.Empty<PendingPayment>();
goto selectCoins; goto selectCoins;
} }
@@ -129,7 +129,27 @@ public class BTCPayCoinjoinCoinSelector : IRoundCoinSelector
goto selectCoins; goto selectCoins;
} }
_wallet.LogTrace(solution.ToString()); _wallet.LogTrace(solution.ToString());
return solution.Coins.ToImmutableList(); return (solution.Coins.ToImmutableList(), async coins =>
{
if (consolidationMode && coins.Count() <8)
{
var cv = new CoinsView(candidates);
var percentage = await _wallet.GetPrivacyPercentageAsync(cv);
var fullyPrivate = await _wallet.IsWalletPrivateAsync(cv);
if(percentage >=1 && fullyPrivate && !solution.HandledPayments.Any() )
{
_wallet.LogTrace("less than ideal coins were registered, so we will abandon this");
return false;
}
}
return true;
} );
} }
private async Task<SubsetSolution> SelectCoinsInternal(UtxoSelectionParameters utxoSelectionParameters, private async Task<SubsetSolution> SelectCoinsInternal(UtxoSelectionParameters utxoSelectionParameters,
@@ -151,14 +171,17 @@ public class BTCPayCoinjoinCoinSelector : IRoundCoinSelector
var cv = new CoinsView(remainingCoins); var cv = new CoinsView(remainingCoins);
var percentage = await _wallet.GetPrivacyPercentageAsync(cv); var percentage = await _wallet.GetPrivacyPercentageAsync(cv);
var fullyPrivate = await _wallet.IsWalletPrivateAsync(new CoinsView(remainingCoins)); var fullyPrivate = await _wallet.IsWalletPrivateAsync(cv);
var coinjoiningOnlyForPayments = fullyPrivate && remainingPendingPayments.Any(); var coinjoiningOnlyForPayments = fullyPrivate && remainingPendingPayments.Any();
if (!consolidationMode && percentage < 1 && _wallet.ConsolidationMode != ConsolidationModeType.Never) if (!consolidationMode && percentage < 1 && _wallet.ConsolidationMode != ConsolidationModeType.Never)
{ {
consolidationMode = true; consolidationMode = true;
} }
solution.ConsolidationMode = consolidationMode; solution.ConsolidationMode = consolidationMode;
if(consolidationMode && coins.Count() < 8 && !coinjoiningOnlyForPayments && ineligibleCoins.Any()) 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. //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.
@@ -270,7 +293,7 @@ public class BTCPayCoinjoinCoinSelector : IRoundCoinSelector
//if we have less than the max suggested output registration, we should add more coins to reach that number to avoid breaking up into too many coins? //if we have less than the max suggested output registration, we should add more coins to reach that number to avoid breaking up into too many coins?
var isLessThanMaxOutputRegistration = solution.Coins.Count < Math.Max(solution.HandledPayments.Count +1, 8); var isLessThanMaxOutputRegistration = solution.Coins.Count < Math.Max(solution.HandledPayments.Count +1, consolidationMode? 11: 10);
var rand = Random.Shared.Next(1, 101); var rand = Random.Shared.Next(1, 101);
//let's check how many coins we are allowed to add max and how many we added, and use that percentage as the random chance of not adding it. //let's check how many coins we are allowed to add max and how many we added, and use that percentage as the random chance of not adding it.
// if max coins = 20, and current coins = 5 then 5/20 = 0.25 * 100 = 25 // if max coins = 20, and current coins = 5 then 5/20 = 0.25 * 100 = 25

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.69</Version> <Version>1.0.70</Version>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup> </PropertyGroup>

View File

@@ -45,13 +45,10 @@ public class BTCPayWallet : IWallet, IDestinationProvider
private readonly BTCPayNetworkJsonSerializerSettings _btcPayNetworkJsonSerializerSettings; private readonly BTCPayNetworkJsonSerializerSettings _btcPayNetworkJsonSerializerSettings;
private readonly Services.Wallets.BTCPayWallet _btcPayWallet; private readonly Services.Wallets.BTCPayWallet _btcPayWallet;
private readonly PullPaymentHostedService _pullPaymentHostedService; private readonly PullPaymentHostedService _pullPaymentHostedService;
// public OnChainPaymentMethodData OnChainPaymentMethodData;
public readonly DerivationStrategyBase DerivationScheme; public readonly DerivationStrategyBase DerivationScheme;
public readonly ExplorerClient ExplorerClient; public readonly ExplorerClient ExplorerClient;
// public readonly IBTCPayServerClientFactory BtcPayServerClientFactory;
public WabisabiStoreSettings WabisabiStoreSettings; public WabisabiStoreSettings WabisabiStoreSettings;
public readonly IUTXOLocker UtxoLocker; public readonly IUTXOLocker UtxoLocker;
// public readonly ILogger Logger;
public static readonly BlockchainAnalyzer BlockchainAnalyzer = new(); public static readonly BlockchainAnalyzer BlockchainAnalyzer = new();
public BTCPayWallet( public BTCPayWallet(
@@ -154,6 +151,11 @@ public class BTCPayWallet : IWallet, IDestinationProvider
return !BatchPayments && privacy >= 1 && !mixToOtherWallet && !forceConsolidate; return !BatchPayments && privacy >= 1 && !mixToOtherWallet && !forceConsolidate;
} }
public bool ForceConsolidate(CoinsView coins, bool isLowFee)
{
return ConsolidationMode == ConsolidationModeType.WhenLowFeeAndManyUTXO && isLowFee && coins.Available().Confirmed().Count() > HighAmountOfCoins;
}
public async Task<double> GetPrivacyPercentageAsync(CoinsView coins) public async Task<double> GetPrivacyPercentageAsync(CoinsView coins)
{ {
return GetPrivacyPercentage(coins, AnonScoreTarget); return GetPrivacyPercentage(coins, AnonScoreTarget);