update wabisabi plugin

This commit is contained in:
Kukks
2023-08-17 10:16:33 +02:00
parent 46d1bbade4
commit d48340e6ea
10 changed files with 74 additions and 50 deletions

View File

@@ -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())

View File

@@ -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">

View File

@@ -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))

View 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 };
}
}

View File

@@ -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>

View File

@@ -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)

View File

@@ -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)
{

View File

@@ -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 () =>