diff --git a/Plugins/BTCPayServer.Plugins.Wabisabi/BTCPayServer.Plugins.Wabisabi.csproj b/Plugins/BTCPayServer.Plugins.Wabisabi/BTCPayServer.Plugins.Wabisabi.csproj index 39152c6..22e71cb 100644 --- a/Plugins/BTCPayServer.Plugins.Wabisabi/BTCPayServer.Plugins.Wabisabi.csproj +++ b/Plugins/BTCPayServer.Plugins.Wabisabi/BTCPayServer.Plugins.Wabisabi.csproj @@ -13,7 +13,7 @@ Wabisabi Coinjoin Allows you to integrate your btcpayserver store with coinjoins. - 1.0.15 + 1.0.16 @@ -43,7 +43,7 @@ - + diff --git a/Plugins/BTCPayServer.Plugins.Wabisabi/BTCPayWallet.cs b/Plugins/BTCPayServer.Plugins.Wabisabi/BTCPayWallet.cs index b75fe4a..6fdc4a6 100644 --- a/Plugins/BTCPayServer.Plugins.Wabisabi/BTCPayWallet.cs +++ b/Plugins/BTCPayServer.Plugins.Wabisabi/BTCPayWallet.cs @@ -110,7 +110,8 @@ public class BTCPayWallet : IWallet, IDestinationProvider public int AnonScoreTarget => WabisabiStoreSettings.PlebMode? 2: WabisabiStoreSettings.AnonymitySetTarget; public bool ConsolidationMode => !WabisabiStoreSettings.PlebMode && WabisabiStoreSettings.ConsolidationMode; - public TimeSpan FeeRateMedianTimeFrame { get; } = TimeSpan.FromHours(KeyManager.DefaultFeeRateMedianTimeFrameHours); + public TimeSpan FeeRateMedianTimeFrame => TimeSpan.FromHours(WabisabiStoreSettings.PlebMode? + KeyManager.DefaultFeeRateMedianTimeFrameHours: WabisabiStoreSettings.FeeRateMedianTimeFrameHours); public bool RedCoinIsolation => !WabisabiStoreSettings.PlebMode &&WabisabiStoreSettings.RedCoinIsolation; public bool BatchPayments => WabisabiStoreSettings.PlebMode || WabisabiStoreSettings.BatchPayments; diff --git a/Plugins/BTCPayServer.Plugins.Wabisabi/Coordinator/WabisabiCoordinatorService.cs b/Plugins/BTCPayServer.Plugins.Wabisabi/Coordinator/WabisabiCoordinatorService.cs index 81bce12..7c26016 100644 --- a/Plugins/BTCPayServer.Plugins.Wabisabi/Coordinator/WabisabiCoordinatorService.cs +++ b/Plugins/BTCPayServer.Plugins.Wabisabi/Coordinator/WabisabiCoordinatorService.cs @@ -3,11 +3,13 @@ using System.IO; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using BTCPayServer; using BTCPayServer.Abstractions.Contracts; using BTCPayServer.Common; using BTCPayServer.Configuration; using BTCPayServer.Plugins.Wabisabi; using BTCPayServer.Services; +using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; @@ -33,6 +35,7 @@ public class WabisabiCoordinatorService : PeriodicRunner private readonly IMemoryCache _memoryCache; private readonly WabisabiCoordinatorClientInstanceManager _instanceManager; private readonly IHttpClientFactory _httpClientFactory; + private readonly LinkGenerator _linkGenerator; public readonly IdempotencyRequestCache IdempotencyRequestCache; @@ -44,7 +47,8 @@ public class WabisabiCoordinatorService : PeriodicRunner IOptions dataDirectories, IExplorerClientProvider clientProvider, IMemoryCache memoryCache, WabisabiCoordinatorClientInstanceManager instanceManager, IHttpClientFactory httpClientFactory, - IServiceProvider serviceProvider) : base(TimeSpan.FromMinutes(15)) + IServiceProvider serviceProvider, + LinkGenerator linkGenerator) : base(TimeSpan.FromMinutes(15)) { _settingsRepository = settingsRepository; _dataDirectories = dataDirectories; @@ -52,6 +56,7 @@ public class WabisabiCoordinatorService : PeriodicRunner _memoryCache = memoryCache; _instanceManager = instanceManager; _httpClientFactory = httpClientFactory; + _linkGenerator = linkGenerator; _socks5HttpClientHandler = serviceProvider.GetRequiredService(); IdempotencyRequestCache = new(memoryCache); } @@ -196,12 +201,13 @@ public class WabisabiCoordinatorService : PeriodicRunner s.UriToAdvertise is not null) { + var uri = new Uri(s.UriToAdvertise, "plugins/wabisabi-coordinator/wabisabi"); await Nostr.Publish(s.NostrRelay, new[] { - await Nostr.CreateCoordinatorDiscoveryEvent(network, s.NostrIdentity, s.UriToAdvertise, + await Nostr.CreateCoordinatorDiscoveryEvent(network, s.NostrIdentity, uri, s.CoordinatorDescription) - }, _socks5HttpClientHandler, cancel); + },s.UriToAdvertise.IsOnion()? _socks5HttpClientHandler: null, cancel); } } } diff --git a/Plugins/BTCPayServer.Plugins.Wabisabi/Coordinator/WabisabiCoordinatorSettings.cs b/Plugins/BTCPayServer.Plugins.Wabisabi/Coordinator/WabisabiCoordinatorSettings.cs index bf72370..11f76c0 100644 --- a/Plugins/BTCPayServer.Plugins.Wabisabi/Coordinator/WabisabiCoordinatorSettings.cs +++ b/Plugins/BTCPayServer.Plugins.Wabisabi/Coordinator/WabisabiCoordinatorSettings.cs @@ -11,7 +11,7 @@ public class WabisabiCoordinatorSettings public bool Enabled { get; set; } = false; public string NostrIdentity { get; set; } - public Uri NostrRelay { get; set; } = new Uri("wss://relay.nostr.info"); + public Uri NostrRelay { get; set; } = new Uri("wss://nostr.mutinywallet.com"); public List DiscoveredCoordinators { get; set; } = new(); @@ -45,5 +45,6 @@ public class DiscoveredCoordinator { public Uri Uri { get; set; } public string Name { get; set; } + public string Relay { get; set; } public string Description { get; set; } } diff --git a/Plugins/BTCPayServer.Plugins.Wabisabi/Nostr.cs b/Plugins/BTCPayServer.Plugins.Wabisabi/Nostr.cs index 9517200..53305d6 100644 --- a/Plugins/BTCPayServer.Plugins.Wabisabi/Nostr.cs +++ b/Plugins/BTCPayServer.Plugins.Wabisabi/Nostr.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Text.Json; +using System.Text.Json.Nodes; using System.Threading; using System.Threading.Tasks; using BTCPayServer.Services; @@ -23,26 +25,37 @@ public class Nostr public static async Task Publish( Uri relayUri, NostrEvent[] evts, - Socks5HttpClientHandler httpClientHandler, + Socks5HttpClientHandler? httpClientHandler, CancellationToken cancellationToken ) { - + if (!evts.Any()) + return; var ct = CancellationTokenSource - .CreateLinkedTokenSource(cancellationToken, new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token) + .CreateLinkedTokenSource(cancellationToken, new CancellationTokenSource(TimeSpan.FromMinutes(1)).Token) .Token; - var client = new NostrClient(relayUri); + var client = new NostrClient(relayUri, socket => socket.Options.Proxy = httpClientHandler?.Proxy); await client.ConnectAndWaitUntilConnected(ct); _ = client.ListenForMessages(); var tcs = new TaskCompletionSource(); var ids = evts.Select(evt => evt.Id).ToHashSet(); - - + client.InvalidMessageReceived += (sender, tuple) => + { + Console.WriteLine(tuple); + + }; + client.OkReceived += (sender, tuple) => + { + if (ids.RemoveWhere(s => s == tuple.eventId)> 0 && !ids.Any()) + { + tcs.TrySetResult(); + } + }; client.EventsReceived += (sender, tuple) => { if (ids.RemoveWhere(s => tuple.events.Any(@event => @event.Id == s)) > 0 && !ids.Any()) { - tcs.TrySetResult(); + tcs.TrySetResult(); } }; await client.CreateSubscription("ack", new[] @@ -86,18 +99,25 @@ public class Nostr } public static async Task> Discover( + Socks5HttpClientHandler? httpClientHandler, Uri relayUri, Network currentNetwork, string ourPubKey, CancellationToken cancellationToken) { - using var nostrClient = new NostrClient(relayUri); + + var nostrClient = new NostrClient(relayUri, socket => socket.Options.Proxy = httpClientHandler?.Proxy); await nostrClient.CreateSubscription("nostr-wabisabi-coordinators", new[] { new NostrSubscriptionFilter() { Kinds = new[] {Kind}, Since = DateTimeOffset.UtcNow.Subtract(TimeSpan.FromHours(1)), + ExtensionData = new Dictionary() + { + ["type"] = JsonSerializer.SerializeToElement(TypeTagValue), + ["network"] = JsonSerializer.SerializeToElement(currentNetwork.Name.ToLower()) + } } }, cancellationToken); var cts = new CancellationTokenSource(TimeSpan.FromMinutes(1)); @@ -107,12 +127,9 @@ public class Nostr var tcs = new TaskCompletionSource(); Stopwatch stopwatch = new(); stopwatch.Start(); - nostrClient.MessageReceived += (sender, s) => + nostrClient.EoseReceived += (sender, s) => { - if (JArray.Parse(s).FirstOrDefault()?.Value() == "EOSE") - { - tcs.SetResult(); - } + tcs.SetResult(); }; nostrClient.EventsReceived += (sender, tuple) => { diff --git a/Plugins/BTCPayServer.Plugins.Wabisabi/Views/Shared/Wabisabi/AddCoordinatorPrompt.cshtml b/Plugins/BTCPayServer.Plugins.Wabisabi/Views/Shared/Wabisabi/AddCoordinatorPrompt.cshtml new file mode 100644 index 0000000..de5d1e0 --- /dev/null +++ b/Plugins/BTCPayServer.Plugins.Wabisabi/Views/Shared/Wabisabi/AddCoordinatorPrompt.cshtml @@ -0,0 +1,81 @@ +@using BTCPayServer.Client +@using Microsoft.AspNetCore.Mvc.TagHelpers +@using BTCPayServer.Abstractions.Contracts +@using BTCPayServer.Abstractions.TagHelpers +@using Newtonsoft.Json +@using WalletWasabi.Backend.Controllers +@model WalletWasabi.Backend.Controllers.DiscoveredCoordinator +@inject IScopeProvider ScopeProvider + + + + + + + + +@if (TempData.TryGetValue("DiscoveredCoordinators" , out var v)&& v is string vs) +{ + var discoveredCoordinators = JsonConvert.DeserializeObject>(vs); + foreach (var coordinator in discoveredCoordinators) + { + + } +} \ No newline at end of file diff --git a/Plugins/BTCPayServer.Plugins.Wabisabi/Views/Shared/Wabisabi/AddManualCoordinator.cshtml b/Plugins/BTCPayServer.Plugins.Wabisabi/Views/Shared/Wabisabi/AddManualCoordinator.cshtml deleted file mode 100644 index ba739a2..0000000 --- a/Plugins/BTCPayServer.Plugins.Wabisabi/Views/Shared/Wabisabi/AddManualCoordinator.cshtml +++ /dev/null @@ -1,36 +0,0 @@ -@using BTCPayServer.Client -@using Microsoft.AspNetCore.Mvc.TagHelpers -@using BTCPayServer.Abstractions.Contracts -@model WalletWasabi.Backend.Controllers.DiscoveredCoordinator -@inject IScopeProvider ScopeProvider - -
- -
-
-
- -
-

Add coordinator manually

- -
- - -
-
- - -
- -
- - -
-
-
-
\ No newline at end of file diff --git a/Plugins/BTCPayServer.Plugins.Wabisabi/Views/Shared/Wabisabi/WabisabiDashboard.cshtml b/Plugins/BTCPayServer.Plugins.Wabisabi/Views/Shared/Wabisabi/WabisabiDashboard.cshtml index 175c705..0e24be1 100644 --- a/Plugins/BTCPayServer.Plugins.Wabisabi/Views/Shared/Wabisabi/WabisabiDashboard.cshtml +++ b/Plugins/BTCPayServer.Plugins.Wabisabi/Views/Shared/Wabisabi/WabisabiDashboard.cshtml @@ -13,7 +13,7 @@ @inject WabisabiService WabisabiService; @inject WalletProvider WalletProvider; @inject WabisabiCoordinatorClientInstanceManager WabisabiCoordinatorClientInstanceManager -@inject ContentSecurityPolicies contentSecurityPolicies + @inject IExplorerClientProvider ExplorerClientProvider @{ @@ -31,10 +31,9 @@ var storeId = ScopeProvider.GetCurrentStoreId(); // var methods = await Client.GetStoreOnChainPaymentMethods(storeId, true); // var method = methods.FirstOrDefault(data => data.CryptoCode == "BTC"); - var nonce = RandomUtils.GetUInt256().ToString().Substring(0, 32); - contentSecurityPolicies.Add("script-src", $"'nonce-{nonce}'"); - contentSecurityPolicies.AllowUnsafeHashes(); - var mainnet = ExplorerClientProvider.GetExplorerClient("BTC").Network.NBitcoinNetwork.ChainName == ChainName.Mainnet; + // var nonce = RandomUtils.GetUInt256().ToString().Substring(0, 32); + // contentSecurityPolicies.Add("script-src", $"'nonce-{nonce}'"); + // contentSecurityPolicies.AllowUnsafeHashes(); } @if (available) diff --git a/Plugins/BTCPayServer.Plugins.Wabisabi/Views/WabisabiStore/UpdateWabisabiStoreSettings.cshtml b/Plugins/BTCPayServer.Plugins.Wabisabi/Views/WabisabiStore/UpdateWabisabiStoreSettings.cshtml index 1c406bf..34f2ffc 100644 --- a/Plugins/BTCPayServer.Plugins.Wabisabi/Views/WabisabiStore/UpdateWabisabiStoreSettings.cshtml +++ b/Plugins/BTCPayServer.Plugins.Wabisabi/Views/WabisabiStore/UpdateWabisabiStoreSettings.cshtml @@ -1,10 +1,10 @@ @using BTCPayServer.Plugins.Wabisabi @using BTCPayServer.Abstractions.Contracts -@using BTCPayServer.Security @using NBitcoin @using System.Security.Claims @using BTCPayServer @using BTCPayServer.Client +@using BTCPayServer.Configuration @using BTCPayServer.Services.Stores @using Microsoft.AspNetCore.Mvc.TagHelpers @using WalletWasabi.Backend.Controllers @@ -14,6 +14,7 @@ @inject StoreRepository StoreRepository @inject WalletProvider WalletProvider @inject BTCPayNetworkProvider BtcPayNetworkProvider +@inject BTCPayServerOptions BtcPayServerOptions @{ var storeId = _scopeProvider.GetCurrentStoreId(); Layout = "../Shared/_NavLayout.cshtml"; @@ -43,6 +44,14 @@
@{ + if (BtcPayServerOptions.SocksEndpoint is null) + { + + } + var wallet = await WalletProvider.GetWalletAsync(storeId); if (wallet is BTCPayWallet btcPayWallet) { @@ -98,6 +107,13 @@

Scores your coinjoined utxos based on how many other utxos in the coinjoin (and other previous coinjoin rounds) had the same value.
Anonset score computation is not an exact science, and when using coordinators with massive liquidity, is not that important as all rounds (past, present, future) contribute to your privacy.

+
+ + + + +

Only coinjoin if the mining fee is below the median of the specified number of hours

+
@@ -217,9 +233,11 @@

} - @if (coordinator.RoundStateUpdater.AnyRound) + // make sure there is a round that is not a blame round + @if (coordinator.RoundStateUpdater.AnyRound && coordinator.RoundStateUpdater.RoundStates.Any(pair => pair.Value.BlameOf == uint256.Zero)) { - var round = coordinator.RoundStateUpdater.RoundStates.Last().Value.CoinjoinState.Parameters; + var round = coordinator.RoundStateUpdater.RoundStates.Last(pair => pair.Value.BlameOf == uint256.Zero).Value; + var roundParameters = round.CoinjoinState.Parameters;