mirror of
https://github.com/aljazceru/BTCPayServerPlugins.git
synced 2025-12-17 23:54:26 +01:00
update wabisabi plugin
This commit is contained in:
@@ -81,7 +81,7 @@ public class BTCPayCoinjoinCoinSelector : IRoundCoinSelector
|
||||
Random.Shared.Next(10, 31),
|
||||
minCoins,
|
||||
new Dictionary<AnonsetType, int>() {{AnonsetType.Red, 1}, {AnonsetType.Orange, 1}, {AnonsetType.Green, 1}},
|
||||
_wallet.ConsolidationMode, liquidityClue);
|
||||
_wallet.ConsolidationMode, liquidityClue, secureRandom);
|
||||
_logger.LogTrace(solution.ToString());
|
||||
return solution.Coins.ToImmutableList();
|
||||
}
|
||||
@@ -90,7 +90,7 @@ public class BTCPayCoinjoinCoinSelector : IRoundCoinSelector
|
||||
IEnumerable<SmartCoin> coins, IEnumerable<PendingPayment> pendingPayments,
|
||||
int maxCoins,
|
||||
Dictionary<AnonsetType, int> maxPerType, Dictionary<AnonsetType, int> idealMinimumPerType,
|
||||
bool consolidationMode, Money liquidityClue)
|
||||
bool consolidationMode, Money liquidityClue, SecureRandom random)
|
||||
{
|
||||
// Sort the coins by their anon score and then by descending order their value, and then slightly randomize in 2 ways:
|
||||
//attempt to shift coins that comes from the same tx AND also attempt to shift coins based on percentage probability
|
||||
@@ -128,7 +128,7 @@ public class BTCPayCoinjoinCoinSelector : IRoundCoinSelector
|
||||
var coinColorCount = solution.SortedCoins.ToDictionary(pair => pair.Key, pair => pair.Value.Length);
|
||||
|
||||
var predicate = new Func<SmartCoin, bool>(_ => true);
|
||||
foreach (var coinColor in idealMinimumPerType.ToShuffled())
|
||||
foreach (var coinColor in idealMinimumPerType.ToShuffled(random))
|
||||
{
|
||||
if (coinColor.Value != 0)
|
||||
{
|
||||
@@ -176,7 +176,7 @@ public class BTCPayCoinjoinCoinSelector : IRoundCoinSelector
|
||||
var potentialPayments = remainingPendingPayments
|
||||
.Where(payment =>
|
||||
payment.ToTxOut().EffectiveCost(utxoSelectionParameters.MiningFeeRate).ToDecimal(MoneyUnit.BTC) <=
|
||||
solution.LeftoverValue).ToShuffled();
|
||||
solution.LeftoverValue).ToShuffled(random);
|
||||
|
||||
while (potentialPayments.Any())
|
||||
{
|
||||
@@ -185,7 +185,7 @@ public class BTCPayCoinjoinCoinSelector : IRoundCoinSelector
|
||||
remainingPendingPayments.Remove(payment);
|
||||
potentialPayments = remainingPendingPayments.Where(payment =>
|
||||
payment.ToTxOut().EffectiveCost(utxoSelectionParameters.MiningFeeRate).ToDecimal(MoneyUnit.BTC) <=
|
||||
solution.LeftoverValue).ToShuffled();
|
||||
solution.LeftoverValue).ToShuffled(random);
|
||||
}
|
||||
|
||||
if (!remainingPendingPayments.Any())
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<PropertyGroup>
|
||||
<Product>Wabisabi Coinjoin</Product>
|
||||
<Description>Allows you to integrate your btcpayserver store with coinjoins.</Description>
|
||||
<Version>1.0.49</Version>
|
||||
<Version>1.0.50</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Plugin development properties -->
|
||||
@@ -43,7 +43,7 @@
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NNostr.Client" Version="0.0.29" />
|
||||
<PackageReference Include="NNostr.Client" Version="0.0.33" />
|
||||
<PackageReference Include="WabiSabi" Version="1.0.1.2" />
|
||||
</ItemGroup>
|
||||
<Target Name="DeleteExampleFile" AfterTargets="Publish">
|
||||
|
||||
@@ -66,8 +66,7 @@ public class BTCPayWallet : IWallet, IDestinationProvider
|
||||
WabisabiStoreSettings wabisabiStoreSettings,
|
||||
IUTXOLocker utxoLocker,
|
||||
ILoggerFactory loggerFactory,
|
||||
StoreRepository storeRepository,
|
||||
ConcurrentDictionary<string, Dictionary<OutPoint, DateTimeOffset>> bannedCoins, EventAggregator eventAggregator)
|
||||
StoreRepository storeRepository)
|
||||
{
|
||||
KeyChain = keyChain;
|
||||
_walletRepository = walletRepository;
|
||||
@@ -82,7 +81,6 @@ public class BTCPayWallet : IWallet, IDestinationProvider
|
||||
WabisabiStoreSettings = wabisabiStoreSettings;
|
||||
UtxoLocker = utxoLocker;
|
||||
_storeRepository = storeRepository;
|
||||
_bannedCoins = bannedCoins;
|
||||
Logger = loggerFactory.CreateLogger($"BTCPayWallet_{storeId}");
|
||||
|
||||
}
|
||||
@@ -149,7 +147,6 @@ public class BTCPayWallet : IWallet, IDestinationProvider
|
||||
private IRoundCoinSelector _coinSelector;
|
||||
public Smartifier _smartifier => (KeyChain as BTCPayKeyChain)?.Smartifier;
|
||||
private readonly StoreRepository _storeRepository;
|
||||
private readonly ConcurrentDictionary<string, Dictionary<OutPoint, DateTimeOffset>> _bannedCoins;
|
||||
|
||||
public IRoundCoinSelector GetCoinSelector()
|
||||
{
|
||||
@@ -229,17 +226,6 @@ public class BTCPayWallet : IWallet, IDestinationProvider
|
||||
|
||||
var locks = await UtxoLocker.FindLocks(utxos.Select(data => data.OutPoint).ToArray());
|
||||
utxos = utxos.Where(data => !locks.Contains(data.OutPoint)).Where(data => data.Confirmations > 0).ToArray();
|
||||
if (_bannedCoins.TryGetValue(coordinatorName, out var bannedCoins))
|
||||
{
|
||||
var expired = bannedCoins.Where(pair => pair.Value < DateTimeOffset.Now).ToArray();
|
||||
foreach (var c in expired)
|
||||
{
|
||||
bannedCoins.Remove(c.Key);
|
||||
|
||||
}
|
||||
|
||||
utxos = utxos.Where(data => !bannedCoins.ContainsKey(data.OutPoint)).ToArray();
|
||||
}
|
||||
await _smartifier.LoadCoins(utxos.Where(data => data.Confirmations>0).ToList(), 1, utxoLabels);
|
||||
|
||||
var resultX = await Task.WhenAll(_smartifier.Coins.Where(pair => utxos.Any(data => data.OutPoint == pair.Key))
|
||||
|
||||
50
Plugins/BTCPayServer.Plugins.Wabisabi/SettingsCoinPrison.cs
Normal file
50
Plugins/BTCPayServer.Plugins.Wabisabi/SettingsCoinPrison.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Services;
|
||||
using Newtonsoft.Json;
|
||||
using WalletWasabi.Logging;
|
||||
using WalletWasabi.WabiSabi.Client.Banning;
|
||||
|
||||
namespace BTCPayServer.Plugins.Wabisabi;
|
||||
|
||||
public class SettingsCoinPrison : CoinPrison
|
||||
{
|
||||
private readonly SettingsRepository _settingsRepository;
|
||||
private readonly string _coordinatorName;
|
||||
|
||||
public SettingsCoinPrison(SettingsRepository settingsRepository, string coordinatorName) : base(null)
|
||||
{
|
||||
_settingsRepository = settingsRepository;
|
||||
_coordinatorName = coordinatorName;
|
||||
}
|
||||
|
||||
protected override void ToFile()
|
||||
{
|
||||
var json = JsonConvert.SerializeObject(BannedCoins, Formatting.Indented);
|
||||
_settingsRepository.UpdateSetting(json, "wabisabi_" + _coordinatorName + "_bannedcoins").GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
public static async Task<SettingsCoinPrison> CreateFromCoordinatorName(SettingsRepository settingsRepository,
|
||||
string coordinatorName)
|
||||
{
|
||||
HashSet<PrisonedCoinRecord> prisonedCoinRecords = new();
|
||||
try
|
||||
{
|
||||
var data = await settingsRepository.GetSettingAsync<string>("wabisabi_" + coordinatorName + "_bannedcoins");
|
||||
if (string.IsNullOrWhiteSpace(data))
|
||||
{
|
||||
Logger.LogDebug("Prisoned coins file is empty.");
|
||||
return new(settingsRepository, coordinatorName);
|
||||
}
|
||||
prisonedCoinRecords = JsonConvert.DeserializeObject<HashSet<PrisonedCoinRecord>>(data)
|
||||
?? throw new InvalidDataException("Prisoned coins file is corrupted.");
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Logger.LogError($"There was an error during loading {nameof(SettingsCoinPrison)}. Ignoring corrupt data.", exc);
|
||||
}
|
||||
return new(settingsRepository, coordinatorName){ BannedCoins = prisonedCoinRecords };
|
||||
}
|
||||
}
|
||||
@@ -299,9 +299,11 @@
|
||||
}
|
||||
</div>
|
||||
@{
|
||||
if (WalletProvider.BannedCoins.TryGetValue(coordinator.CoordinatorName, out var bannedCoinsList))
|
||||
|
||||
if (coordinator.CoinPrison is not null)
|
||||
{
|
||||
var bannedCoins = coins.Where(coin => bannedCoinsList.ContainsKey(coin.Outpoint));
|
||||
|
||||
var bannedCoins = coins.Where(coin => coordinator.CoinPrison.TryGetOrRemoveBannedCoin(coin.Outpoint, out _));
|
||||
@if (bannedCoins.Any())
|
||||
{
|
||||
<div>
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Payments.PayJoin;
|
||||
using BTCPayServer.Services;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
@@ -15,6 +16,7 @@ using WalletWasabi.Tor.Socks5.Pool.Circuits;
|
||||
using WalletWasabi.Userfacing;
|
||||
using WalletWasabi.WabiSabi.Backend.PostRequests;
|
||||
using WalletWasabi.WabiSabi.Client;
|
||||
using WalletWasabi.WabiSabi.Client.Banning;
|
||||
using WalletWasabi.WabiSabi.Client.RoundStateAwaiters;
|
||||
using WalletWasabi.WabiSabi.Client.StatusChangedEvents;
|
||||
using WalletWasabi.Wallets;
|
||||
@@ -137,6 +139,7 @@ public class WabisabiCoordinatorClientInstance
|
||||
public string TermsConditions { get; set; }
|
||||
public HttpClientFactory WasabiHttpClientFactory { get; set; }
|
||||
public RoundStateUpdater RoundStateUpdater { get; set; }
|
||||
public CoinPrison CoinPrison { get; private set; }
|
||||
public WasabiCoordinatorStatusFetcher WasabiCoordinatorStatusFetcher { get; set; }
|
||||
public CoinJoinManager CoinJoinManager { get; set; }
|
||||
public string Description { get; set; }
|
||||
@@ -196,24 +199,22 @@ public class WabisabiCoordinatorClientInstance
|
||||
WasabiCoordinatorStatusFetcher = new WasabiCoordinatorStatusFetcher(sharedWabisabiClient, _logger);
|
||||
|
||||
RoundStateUpdater = new RoundStateUpdater(TimeSpan.FromSeconds(5),sharedWabisabiClient, WasabiCoordinatorStatusFetcher);
|
||||
|
||||
CoinPrison = SettingsCoinPrison.CreateFromCoordinatorName(serviceProvider.GetRequiredService<SettingsRepository>(),
|
||||
CoordinatorName).GetAwaiter().GetResult();
|
||||
if (coordinatorName == "local")
|
||||
{
|
||||
CoinJoinManager = new CoinJoinManager(coordinatorName, WalletProvider, RoundStateUpdater,
|
||||
sharedWabisabiClient, null,
|
||||
WasabiCoordinatorStatusFetcher, coordinatorIdentifier);
|
||||
WasabiCoordinatorStatusFetcher, coordinatorIdentifier, CoinPrison);
|
||||
}
|
||||
else
|
||||
{
|
||||
CoinJoinManager = new CoinJoinManager(coordinatorName,WalletProvider, RoundStateUpdater,null, WasabiHttpClientFactory,
|
||||
WasabiCoordinatorStatusFetcher, coordinatorIdentifier);
|
||||
WasabiCoordinatorStatusFetcher, coordinatorIdentifier, CoinPrison);
|
||||
}
|
||||
|
||||
CoinJoinManager.StatusChanged += OnStatusChanged;
|
||||
CoinJoinManager.OnBan += (sender, args) =>
|
||||
{
|
||||
WalletProvider.OnBan(coordinatorName, args);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public async Task StopWallet(IWallet wallet)
|
||||
|
||||
@@ -20,7 +20,7 @@ public class WabisabiPlugin : BaseBTCPayServerPlugin
|
||||
{
|
||||
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
||||
{
|
||||
new() { Identifier = nameof(BTCPayServer), Condition = ">=1.10.0" }
|
||||
new() { Identifier = nameof(BTCPayServer), Condition = ">=1.11.0" }
|
||||
};
|
||||
public override void Execute(IServiceCollection applicationBuilder)
|
||||
{
|
||||
|
||||
@@ -58,9 +58,7 @@ public class WalletProvider : PeriodicRunner,IWalletProvider
|
||||
}
|
||||
|
||||
public readonly ConcurrentDictionary<string, Task<IWallet?>> LoadedWallets = new();
|
||||
public ConcurrentDictionary<string, Dictionary<OutPoint, DateTimeOffset>> BannedCoins = new();
|
||||
|
||||
|
||||
public class WalletUnloadEventArgs : EventArgs
|
||||
{
|
||||
public IWallet Wallet { get; }
|
||||
@@ -129,8 +127,7 @@ public class WalletProvider : PeriodicRunner,IWalletProvider
|
||||
_serviceProvider.GetRequiredService<PullPaymentHostedService>(),derivationStrategy, explorerClient, keychain,
|
||||
name, wabisabiStoreSettings, UtxoLocker,
|
||||
_loggerFactory,
|
||||
_serviceProvider.GetRequiredService<StoreRepository>(), BannedCoins,
|
||||
_eventAggregator);
|
||||
_serviceProvider.GetRequiredService<StoreRepository>());
|
||||
|
||||
});
|
||||
|
||||
@@ -273,18 +270,6 @@ public class WalletProvider : PeriodicRunner,IWalletProvider
|
||||
await GetWalletAsync(storeId);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnBan(string coordinatorName, BannedCoinEventArgs args)
|
||||
{
|
||||
BannedCoins.AddOrUpdate(coordinatorName,
|
||||
s => new Dictionary<OutPoint, DateTimeOffset>() {{args.Utxo, args.BannedTime}},
|
||||
(s, offsets) =>
|
||||
{
|
||||
offsets.TryAdd(args.Utxo, args.BannedTime);
|
||||
return offsets;
|
||||
});
|
||||
}
|
||||
|
||||
public override Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
|
||||
Submodule submodules/btcpayserver updated: 2538f3d8f6...b3df403980
Submodule submodules/walletwasabi updated: a6d6439a2a...ad2cc23b76
Reference in New Issue
Block a user