diff --git a/BTCPayServer.Client/BTCPayServer.Client.csproj b/BTCPayServer.Client/BTCPayServer.Client.csproj index dc8156bad..9a475304f 100644 --- a/BTCPayServer.Client/BTCPayServer.Client.csproj +++ b/BTCPayServer.Client/BTCPayServer.Client.csproj @@ -27,8 +27,8 @@ - - + + diff --git a/BTCPayServer.Common/BTCPayServer.Common.csproj b/BTCPayServer.Common/BTCPayServer.Common.csproj index c94ff5a5d..bcba4d9db 100644 --- a/BTCPayServer.Common/BTCPayServer.Common.csproj +++ b/BTCPayServer.Common/BTCPayServer.Common.csproj @@ -4,7 +4,7 @@ - + diff --git a/BTCPayServer.Rating/BTCPayServer.Rating.csproj b/BTCPayServer.Rating/BTCPayServer.Rating.csproj index f6c2529b6..55038beb2 100644 --- a/BTCPayServer.Rating/BTCPayServer.Rating.csproj +++ b/BTCPayServer.Rating/BTCPayServer.Rating.csproj @@ -6,7 +6,7 @@ - + diff --git a/BTCPayServer.Tests/GreenfieldAPITests.cs b/BTCPayServer.Tests/GreenfieldAPITests.cs index 8fecff68e..18e51ba6f 100644 --- a/BTCPayServer.Tests/GreenfieldAPITests.cs +++ b/BTCPayServer.Tests/GreenfieldAPITests.cs @@ -1937,7 +1937,7 @@ namespace BTCPayServer.Tests } var methods = await adminClient.GetStorePaymentMethods(store.Id); - Assert.Equal(1, methods.Count); + Assert.Single(methods); VerifyLightning(methods); var randK = new Mnemonic(Wordlist.English, WordCount.Twelve).DeriveExtKey().Neuter().ToString(Network.RegTest); diff --git a/BTCPayServer.Tests/PayJoinTests.cs b/BTCPayServer.Tests/PayJoinTests.cs index ac9ba286c..ec6f19e4d 100644 --- a/BTCPayServer.Tests/PayJoinTests.cs +++ b/BTCPayServer.Tests/PayJoinTests.cs @@ -146,7 +146,7 @@ namespace BTCPayServer.Tests { var tx = network.NBitcoinNetwork.CreateTransaction(); tx.Inputs.Add(new OutPoint(RandomUtils.GetUInt256(), 0), Script.Empty); - tx.Outputs.Add(Money.Coins(1.0m), new Key().ScriptPubKey); + tx.Outputs.Add(Money.Coins(1.0m), new Key().GetScriptPubKey(ScriptPubKeyType.Legacy)); return tx; } @@ -184,12 +184,16 @@ namespace BTCPayServer.Tests foreach (ScriptPubKeyType senderAddressType in Enum.GetValues(typeof(ScriptPubKeyType))) { + if (senderAddressType == ScriptPubKeyType.TaprootBIP86) + continue; var senderUser = tester.NewAccount(); senderUser.GrantAccess(true); senderUser.RegisterDerivationScheme("BTC", senderAddressType); foreach (ScriptPubKeyType receiverAddressType in Enum.GetValues(typeof(ScriptPubKeyType))) { + if (receiverAddressType == ScriptPubKeyType.TaprootBIP86) + continue; var senderCoin = await senderUser.ReceiveUTXO(Money.Satoshis(100000), network); Logs.Tester.LogInformation($"Testing payjoin with sender: {senderAddressType} receiver: {receiverAddressType}"); diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index f46cfa292..6c6a4fe01 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -1689,7 +1689,10 @@ namespace BTCPayServer.Tests var invoice2Address = BitcoinAddress.Create(invoice2.BitcoinAddress, user.SupportedNetwork.NBitcoinNetwork); uint256 invoice2tx1Id = - await tester.ExplorerNode.SendToAddressAsync(invoice2Address, invoice2.BtcDue, replaceable: true); + await tester.ExplorerNode.SendToAddressAsync(invoice2Address, invoice2.BtcDue, new NBitcoin.RPC.SendToAddressParameters() + { + Replaceable = true + }); Transaction invoice2Tx1 = null; TestUtils.Eventually(() => { @@ -1707,7 +1710,7 @@ namespace BTCPayServer.Tests output = invoice2Tx2.Outputs.First(o => o.ScriptPubKey == invoice2Address.ScriptPubKey); output.Value -= new Money(10_000, MoneyUnit.Satoshi); - output.ScriptPubKey = new Key().ScriptPubKey; + output.ScriptPubKey = new Key().GetScriptPubKey(ScriptPubKeyType.Legacy); invoice2Tx2 = await tester.ExplorerNode.SignRawTransactionAsync(invoice2Tx2); await tester.ExplorerNode.SendRawTransactionAsync(invoice2Tx2); tester.ExplorerNode.Generate(1); diff --git a/BTCPayServer.Tests/docker-compose.altcoins.yml b/BTCPayServer.Tests/docker-compose.altcoins.yml index 38eaa74d9..6d0ea1bb6 100644 --- a/BTCPayServer.Tests/docker-compose.altcoins.yml +++ b/BTCPayServer.Tests/docker-compose.altcoins.yml @@ -84,7 +84,7 @@ services: - customer_lnd - merchant_lnd nbxplorer: - image: nicolasdorier/nbxplorer:2.1.49 + image: nicolasdorier/nbxplorer:2.1.53 restart: unless-stopped ports: - "32838:32838" diff --git a/BTCPayServer.Tests/docker-compose.yml b/BTCPayServer.Tests/docker-compose.yml index d148430cc..aa84040aa 100644 --- a/BTCPayServer.Tests/docker-compose.yml +++ b/BTCPayServer.Tests/docker-compose.yml @@ -81,7 +81,7 @@ services: - customer_lnd - merchant_lnd nbxplorer: - image: nicolasdorier/nbxplorer:2.1.49 + image: nicolasdorier/nbxplorer:2.1.53 restart: unless-stopped ports: - "32838:32838" diff --git a/BTCPayServer/BTCPayServer.csproj b/BTCPayServer/BTCPayServer.csproj index f9e7c2b81..e83a4067c 100644 --- a/BTCPayServer/BTCPayServer.csproj +++ b/BTCPayServer/BTCPayServer.csproj @@ -46,7 +46,7 @@ - + diff --git a/BTCPayServer/Controllers/GreenField/LocalBTCPayServerClient.cs b/BTCPayServer/Controllers/GreenField/LocalBTCPayServerClient.cs index 2b95790c6..374a9ca1b 100644 --- a/BTCPayServer/Controllers/GreenField/LocalBTCPayServerClient.cs +++ b/BTCPayServer/Controllers/GreenField/LocalBTCPayServerClient.cs @@ -504,11 +504,11 @@ namespace BTCPayServer.Controllers.GreenField return Task.FromResult(GetFromActionResult(_chainPaymentMethodsController.GetOnChainPaymentMethods(storeId, enabled))); } - public override async Task GetStoreOnChainPaymentMethod(string storeId, + public override Task GetStoreOnChainPaymentMethod(string storeId, string cryptoCode, CancellationToken token = default) { - return GetFromActionResult( - await _chainPaymentMethodsController.GetOnChainPaymentMethod(storeId, cryptoCode)); + return Task.FromResult(GetFromActionResult( + _chainPaymentMethodsController.GetOnChainPaymentMethod(storeId, cryptoCode))); } public override async Task RemoveStoreOnChainPaymentMethod(string storeId, string cryptoCode, @@ -534,13 +534,13 @@ namespace BTCPayServer.Controllers.GreenField paymentMethod, offset, amount))); } - public override async Task PreviewStoreOnChainPaymentMethodAddresses( + public override Task PreviewStoreOnChainPaymentMethodAddresses( string storeId, string cryptoCode, int offset = 0, int amount = 10, CancellationToken token = default) { - return GetFromActionResult( - await _chainPaymentMethodsController.GetOnChainPaymentMethodPreview(storeId, cryptoCode, offset, - amount)); + return Task.FromResult(GetFromActionResult( + _chainPaymentMethodsController.GetOnChainPaymentMethodPreview(storeId, cryptoCode, offset, + amount))); } public override Task GetHealth(CancellationToken token = default) diff --git a/BTCPayServer/Controllers/GreenField/StoreLightningNetworkPaymentMethodsController.cs b/BTCPayServer/Controllers/GreenField/StoreLightningNetworkPaymentMethodsController.cs index aba85e167..3dc236985 100644 --- a/BTCPayServer/Controllers/GreenField/StoreLightningNetworkPaymentMethodsController.cs +++ b/BTCPayServer/Controllers/GreenField/StoreLightningNetworkPaymentMethodsController.cs @@ -1,5 +1,6 @@ #nullable enable using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; using BTCPayServer.Abstractions.Constants; @@ -122,7 +123,7 @@ namespace BTCPayServer.Controllers.GreenField return NotFound(); } - if (string.IsNullOrEmpty(paymentMethodData?.ConnectionString)) + if (string.IsNullOrEmpty(paymentMethodData.ConnectionString)) { ModelState.AddModelError(nameof(LightningNetworkPaymentMethodData.ConnectionString), "Missing connectionString"); @@ -131,8 +132,8 @@ namespace BTCPayServer.Controllers.GreenField if (!ModelState.IsValid) return this.CreateValidationError(ModelState); - LightningSupportedPaymentMethod paymentMethod = null; - if (!string.IsNullOrEmpty(paymentMethodData.ConnectionString)) + LightningSupportedPaymentMethod? paymentMethod = null; + if (!string.IsNullOrEmpty(paymentMethodData!.ConnectionString)) { if (paymentMethodData.ConnectionString == LightningSupportedPaymentMethod.InternalNode) { @@ -189,8 +190,8 @@ namespace BTCPayServer.Controllers.GreenField return Ok(GetExistingLightningLikePaymentMethod(cryptoCode, store)); } - private LightningNetworkPaymentMethodData GetExistingLightningLikePaymentMethod(string cryptoCode, - StoreData store = null) + private LightningNetworkPaymentMethodData? GetExistingLightningLikePaymentMethod(string cryptoCode, + StoreData? store = null) { store ??= Store; var storeBlob = store.GetStoreBlob(); @@ -201,13 +202,13 @@ namespace BTCPayServer.Controllers.GreenField .FirstOrDefault(method => method.PaymentId == id); var excluded = storeBlob.IsExcluded(id); - return paymentMethod == null + return paymentMethod is null ? null : new LightningNetworkPaymentMethodData(paymentMethod.PaymentId.CryptoCode, paymentMethod.GetDisplayableConnectionString(), !excluded); } - private bool GetNetwork(string cryptoCode, out BTCPayNetwork network) + private bool GetNetwork(string cryptoCode, [MaybeNullWhen(false)] out BTCPayNetwork network) { network = _btcPayNetworkProvider.GetNetwork(cryptoCode); network = network?.SupportLightning is true ? network : null; diff --git a/BTCPayServer/Controllers/GreenField/StoreOnChainPaymentMethodsController.cs b/BTCPayServer/Controllers/GreenField/StoreOnChainPaymentMethodsController.cs index 1e7b1331f..a231b0f6c 100644 --- a/BTCPayServer/Controllers/GreenField/StoreOnChainPaymentMethodsController.cs +++ b/BTCPayServer/Controllers/GreenField/StoreOnChainPaymentMethodsController.cs @@ -73,7 +73,7 @@ namespace BTCPayServer.Controllers.GreenField [Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)] [HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}")] - public async Task> GetOnChainPaymentMethod( + public ActionResult GetOnChainPaymentMethod( string storeId, string cryptoCode) { @@ -93,7 +93,7 @@ namespace BTCPayServer.Controllers.GreenField [Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)] [HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/preview")] - public async Task GetOnChainPaymentMethodPreview( + public IActionResult GetOnChainPaymentMethodPreview( string storeId, string cryptoCode, int offset = 0, int amount = 10) diff --git a/BTCPayServer/Controllers/GreenField/StoreOnChainWalletsController.cs b/BTCPayServer/Controllers/GreenField/StoreOnChainWalletsController.cs index 2fee77dc3..493e79566 100644 --- a/BTCPayServer/Controllers/GreenField/StoreOnChainWalletsController.cs +++ b/BTCPayServer/Controllers/GreenField/StoreOnChainWalletsController.cs @@ -1,6 +1,7 @@ #nullable enable using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Threading; @@ -83,8 +84,8 @@ namespace BTCPayServer.Controllers.GreenField [HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet")] public async Task ShowOnChainWalletOverview(string storeId, string cryptoCode) { - if (IsInvalidWalletRequest(cryptoCode, out BTCPayNetwork network, - out DerivationSchemeSettings derivationScheme, out IActionResult actionResult)) return actionResult; + if (IsInvalidWalletRequest(cryptoCode, out var network, + out var derivationScheme, out var actionResult)) return actionResult; var wallet = _btcPayWalletProvider.GetWallet(network); var balance = await wallet.GetBalance(derivationScheme.AccountDerivation); @@ -102,8 +103,8 @@ namespace BTCPayServer.Controllers.GreenField [HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/feerate")] public async Task GetOnChainFeeRate(string storeId, string cryptoCode, int? blockTarget = null) { - if (IsInvalidWalletRequest(cryptoCode, out BTCPayNetwork network, - out DerivationSchemeSettings derivationScheme, out IActionResult actionResult)) return actionResult; + if (IsInvalidWalletRequest(cryptoCode, out var network, + out var derivationScheme, out var actionResult)) return actionResult; var feeRateTarget = blockTarget?? Store.GetStoreBlob().RecommendedFeeBlockTarget; return Ok(new OnChainWalletFeeRateData() @@ -117,8 +118,8 @@ namespace BTCPayServer.Controllers.GreenField [HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/address")] public async Task GetOnChainWalletReceiveAddress(string storeId, string cryptoCode, bool forceGenerate = false) { - if (IsInvalidWalletRequest(cryptoCode, out BTCPayNetwork network, - out DerivationSchemeSettings derivationScheme, out IActionResult actionResult)) return actionResult; + if (IsInvalidWalletRequest(cryptoCode, out var network, + out var derivationScheme, out var actionResult)) return actionResult; var kpi = await _walletReceiveService.GetOrGenerate(new WalletId(storeId, cryptoCode), forceGenerate); if (kpi is null) @@ -145,8 +146,8 @@ namespace BTCPayServer.Controllers.GreenField [HttpDelete("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/address")] public async Task UnReserveOnChainWalletReceiveAddress(string storeId, string cryptoCode) { - if (IsInvalidWalletRequest(cryptoCode, out BTCPayNetwork network, - out DerivationSchemeSettings derivationScheme, out IActionResult actionResult)) return actionResult; + if (IsInvalidWalletRequest(cryptoCode, out var network, + out var derivationScheme, out var actionResult)) return actionResult; var addr = await _walletReceiveService.UnReserveAddress(new WalletId(storeId, cryptoCode)); if (addr is null) @@ -166,8 +167,8 @@ namespace BTCPayServer.Controllers.GreenField [FromQuery] int limit = int.MaxValue ) { - if (IsInvalidWalletRequest(cryptoCode, out BTCPayNetwork network, - out DerivationSchemeSettings derivationScheme, out IActionResult actionResult)) return actionResult; + if (IsInvalidWalletRequest(cryptoCode, out var network, + out var derivationScheme, out var actionResult)) return actionResult; var wallet = _btcPayWalletProvider.GetWallet(network); var walletId = new WalletId(storeId, cryptoCode); @@ -203,8 +204,8 @@ namespace BTCPayServer.Controllers.GreenField public async Task GetOnChainWalletTransaction(string storeId, string cryptoCode, string transactionId) { - if (IsInvalidWalletRequest(cryptoCode, out BTCPayNetwork network, - out DerivationSchemeSettings derivationScheme, out IActionResult actionResult)) return actionResult; + if (IsInvalidWalletRequest(cryptoCode, out var network, + out var derivationScheme, out var actionResult)) return actionResult; var wallet = _btcPayWalletProvider.GetWallet(network); var tx = await wallet.FetchTransaction(derivationScheme.AccountDerivation, uint256.Parse(transactionId)); @@ -225,8 +226,8 @@ namespace BTCPayServer.Controllers.GreenField [HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/utxos")] public async Task GetOnChainWalletUTXOs(string storeId, string cryptoCode) { - if (IsInvalidWalletRequest(cryptoCode, out BTCPayNetwork network, - out DerivationSchemeSettings derivationScheme, out IActionResult actionResult)) return actionResult; + if (IsInvalidWalletRequest(cryptoCode, out var network, + out var derivationScheme, out var actionResult)) return actionResult; var wallet = _btcPayWalletProvider.GetWallet(network); @@ -258,8 +259,8 @@ namespace BTCPayServer.Controllers.GreenField public async Task CreateOnChainTransaction(string storeId, string cryptoCode, [FromBody] CreateOnChainTransactionRequest request) { - if (IsInvalidWalletRequest(cryptoCode, out BTCPayNetwork network, - out DerivationSchemeSettings derivationScheme, out IActionResult actionResult)) return actionResult; + if (IsInvalidWalletRequest(cryptoCode, out var network, + out var derivationScheme, out var actionResult)) return actionResult; if (network.ReadonlyWallet) { return this.CreateAPIError("not-available", @@ -445,8 +446,13 @@ namespace BTCPayServer.Controllers.GreenField psbt.PSBT.RebaseKeyPaths(signingKeySettings.AccountKey, rootedKeyPath); var accountKey = signingKey.Derive(rootedKeyPath.KeyPath); + if (signingContext?.EnforceLowR is bool v) + psbt.PSBT.Settings.SigningOptions.EnforceLowR = v; + else if (psbt.Suggestions?.ShouldEnforceLowR is bool v2) + psbt.PSBT.Settings.SigningOptions.EnforceLowR = v2; + var changed = psbt.PSBT.PSBTChanged(() => psbt.PSBT.SignAll(derivationScheme.AccountDerivation, accountKey, - rootedKeyPath, new SigningOptions() {EnforceLowR = signingContext?.EnforceLowR is bool v ? v : psbt.Suggestions.ShouldEnforceLowR })); + rootedKeyPath)); if (!changed) { @@ -458,7 +464,7 @@ namespace BTCPayServer.Controllers.GreenField var transaction = psbt.PSBT.ExtractTransaction(); var transactionHash = transaction.GetHash(); BroadcastResult broadcastResult; - if (!string.IsNullOrEmpty(signingContext.PayJoinBIP21)) + if (!string.IsNullOrEmpty(signingContext?.PayJoinBIP21)) { signingContext.OriginalPSBT = psbt.PSBT.ToBase64(); try @@ -468,8 +474,8 @@ namespace BTCPayServer.Controllers.GreenField var payjoinPSBT = await _payjoinClient.RequestPayjoin( new BitcoinUrlBuilder(signingContext.PayJoinBIP21, network.NBitcoinNetwork), new PayjoinWallet(derivationScheme), psbt.PSBT, CancellationToken.None); - payjoinPSBT = psbt.PSBT.SignAll(derivationScheme.AccountDerivation, accountKey, rootedKeyPath, - new SigningOptions() {EnforceLowR = !(signingContext?.EnforceLowR is false)}); + psbt.PSBT.Settings.SigningOptions = new SigningOptions() { EnforceLowR = !(signingContext?.EnforceLowR is false) }; + payjoinPSBT = psbt.PSBT.SignAll(derivationScheme.AccountDerivation, accountKey, rootedKeyPath); payjoinPSBT.Finalize(); var payjoinTransaction = payjoinPSBT.ExtractTransaction(); var hash = payjoinTransaction.GetHash(); @@ -508,11 +514,10 @@ namespace BTCPayServer.Controllers.GreenField return await _authorizationService.CanUseHotWallet(await _settingsRepository.GetPolicies(), User); } - private bool IsInvalidWalletRequest(string cryptoCode, out BTCPayNetwork network, - out DerivationSchemeSettings derivationScheme, out IActionResult actionResult) + private bool IsInvalidWalletRequest(string cryptoCode, [MaybeNullWhen(true)] out BTCPayNetwork network, + [MaybeNullWhen(true)] out DerivationSchemeSettings derivationScheme, [MaybeNullWhen(false)] out IActionResult actionResult) { derivationScheme = null; - actionResult = null; network = _btcPayNetworkProvider.GetNetwork(cryptoCode); if (network is null) { @@ -535,6 +540,7 @@ namespace BTCPayServer.Controllers.GreenField return true; } + actionResult = null; return false; } diff --git a/BTCPayServer/Controllers/InvoiceController.UI.cs b/BTCPayServer/Controllers/InvoiceController.UI.cs index 99e598a00..ae3fe241c 100644 --- a/BTCPayServer/Controllers/InvoiceController.UI.cs +++ b/BTCPayServer/Controllers/InvoiceController.UI.cs @@ -440,9 +440,9 @@ namespace BTCPayServer.Controllers { //Keep compatibility with Bitpay invoiceId = invoiceId ?? id; - id = invoiceId; // - + if (invoiceId is null) + return NotFound(); var model = await GetInvoiceModel(invoiceId, paymentMethodId == null ? null : PaymentMethodId.Parse(paymentMethodId), lang); if (model == null) return NotFound(); @@ -472,24 +472,24 @@ namespace BTCPayServer.Controllers { //Keep compatibility with Bitpay invoiceId = invoiceId ?? id; - id = invoiceId; // - - var model = await GetInvoiceModel(invoiceId, paymentMethodId == null ? null : PaymentMethodId.Parse(paymentMethodId), lang); + if (invoiceId is null) + return NotFound(); + var model = await GetInvoiceModel(invoiceId, paymentMethodId is null ? null : PaymentMethodId.Parse(paymentMethodId), lang); if (model == null) return NotFound(); return View(model); } - private async Task GetInvoiceModel(string invoiceId, PaymentMethodId paymentMethodId, string? lang) + private async Task GetInvoiceModel(string invoiceId, PaymentMethodId? paymentMethodId, string? lang) { var invoice = await _InvoiceRepository.GetInvoice(invoiceId); if (invoice == null) return null; var store = await _StoreRepository.FindStore(invoice.StoreId); bool isDefaultPaymentId = false; - if (paymentMethodId == null) + if (paymentMethodId is null) { paymentMethodId = store.GetDefaultPaymentId(_NetworkProvider); isDefaultPaymentId = true; @@ -846,6 +846,11 @@ namespace BTCPayServer.Controllers ModelState.AddModelError(nameof(model.StoreId), "You need to configure the derivation scheme in order to create an invoice"); return View(model); } + if (model.Amount is null) + { + ModelState.AddModelError(nameof(model.Amount), "Thhe invoice amount can't be empty"); + return View(model); + } try { @@ -910,7 +915,7 @@ namespace BTCPayServer.Controllers public class InvoiceStateChangeModel { public bool NotFound { get; set; } - public string StatusString { get; set; } + public string? StatusString { get; set; } } private string GetUserId() @@ -933,7 +938,7 @@ namespace BTCPayServer.Controllers var jObject = JObject.Parse(posData); foreach (var item in jObject) { - switch (item.Value.Type) + switch (item.Value?.Type) { case JTokenType.Array: var items = item.Value.AsEnumerable().ToList(); @@ -945,6 +950,8 @@ namespace BTCPayServer.Controllers case JTokenType.Object: result.TryAdd(item.Key, ParsePosData(item.Value.ToString())); break; + case null: + break; default: result.TryAdd(item.Key, item.Value.ToString()); break; diff --git a/BTCPayServer/Controllers/WalletsController.PSBT.cs b/BTCPayServer/Controllers/WalletsController.PSBT.cs index e58f63cdf..8078cf969 100644 --- a/BTCPayServer/Controllers/WalletsController.PSBT.cs +++ b/BTCPayServer/Controllers/WalletsController.PSBT.cs @@ -335,13 +335,14 @@ namespace BTCPayServer.Controllers derivationSchemeSettings, network, cancellationToken); try { + proposedPayjoin.Settings.SigningOptions = new SigningOptions() + { + EnforceLowR = !(vm.SigningContext?.EnforceLowR is false) + }; var extKey = ExtKey.Parse(vm.SigningKey, network.NBitcoinNetwork); proposedPayjoin = proposedPayjoin.SignAll(derivationSchemeSettings.AccountDerivation, extKey, - RootedKeyPath.Parse(vm.SigningKeyPath), new SigningOptions() - { - EnforceLowR = !(vm.SigningContext?.EnforceLowR is false) - }); + RootedKeyPath.Parse(vm.SigningKeyPath)); vm.SigningContext.PSBT = proposedPayjoin.ToBase64(); vm.SigningContext.OriginalPSBT = psbt.ToBase64(); proposedPayjoin.Finalize(); diff --git a/BTCPayServer/Controllers/WalletsController.cs b/BTCPayServer/Controllers/WalletsController.cs index 6917a5ba1..b1ca982b9 100644 --- a/BTCPayServer/Controllers/WalletsController.cs +++ b/BTCPayServer/Controllers/WalletsController.cs @@ -925,10 +925,11 @@ namespace BTCPayServer.Controllers return View(nameof(SignWithSeed), viewModel); } - var changed = psbt.PSBTChanged( () => psbt.SignAll(settings.AccountDerivation, signingKey, rootedKeyPath, new SigningOptions() + psbt.Settings.SigningOptions = new SigningOptions() { EnforceLowR = !(viewModel.SigningContext?.EnforceLowR is false) - })); + }; + var changed = psbt.PSBTChanged( () => psbt.SignAll(settings.AccountDerivation, signingKey, rootedKeyPath)); if (!changed) { ModelState.AddModelError(nameof(viewModel.SeedOrKey), "Impossible to sign the transaction. Probable causes: Incorrect account key path in wallet settings or PSBT already signed."); diff --git a/BTCPayServer/Data/Payouts/BitcoinLike/BitcoinLikePayoutHandler.cs b/BTCPayServer/Data/Payouts/BitcoinLike/BitcoinLikePayoutHandler.cs index 0c8cd80fa..69ac1de60 100644 --- a/BTCPayServer/Data/Payouts/BitcoinLike/BitcoinLikePayoutHandler.cs +++ b/BTCPayServer/Data/Payouts/BitcoinLike/BitcoinLikePayoutHandler.cs @@ -302,7 +302,9 @@ public class BitcoinLikePayoutHandler : IPayoutHandler .ThenInclude(o => o.StoreData) .Where(p => p.State == PayoutState.AwaitingPayment) .Where(p => p.PaymentMethodId == paymentMethodId.ToString()) +#pragma warning disable CA1307 // Specify StringComparison .Where(p => destination.Equals(p.Destination)) +#pragma warning restore CA1307 // Specify StringComparison .ToListAsync(); var payoutByDestination = payouts.ToDictionary(p => p.Destination); diff --git a/BTCPayServer/DerivationSchemeParser.cs b/BTCPayServer/DerivationSchemeParser.cs index 7e8d9845f..8fd05af63 100644 --- a/BTCPayServer/DerivationSchemeParser.cs +++ b/BTCPayServer/DerivationSchemeParser.cs @@ -47,7 +47,7 @@ namespace BTCPayServer if (str == null) throw new ArgumentNullException(nameof(str)); str = str.Trim(); - var outputDescriptor = OutputDescriptor.Parse(str); + var outputDescriptor = OutputDescriptor.Parse(str, Network); switch(outputDescriptor) { case OutputDescriptor.PK _: diff --git a/BTCPayServer/HostedServices/WebhookNotificationManager.cs b/BTCPayServer/HostedServices/WebhookNotificationManager.cs index a73c96c2d..1bf72cbd9 100644 --- a/BTCPayServer/HostedServices/WebhookNotificationManager.cs +++ b/BTCPayServer/HostedServices/WebhookNotificationManager.cs @@ -270,7 +270,7 @@ namespace BTCPayServer.HostedServices await Task.Delay(wait, CancellationToken); ctx = await CreateRedeliveryRequest(originalDeliveryId); // This may have changed - if (!ctx.WebhookBlob.AutomaticRedelivery || + if (ctx is null || !ctx.WebhookBlob.AutomaticRedelivery || !ShouldDeliver(ctx.WebhookEvent.Type, ctx.WebhookBlob)) break; result = await SendAndSaveDelivery(ctx); diff --git a/BTCPayServer/Models/StoreViewModels/WebhooksViewModel.cs b/BTCPayServer/Models/StoreViewModels/WebhooksViewModel.cs index f19b4fa87..e4c09daff 100644 --- a/BTCPayServer/Models/StoreViewModels/WebhooksViewModel.cs +++ b/BTCPayServer/Models/StoreViewModels/WebhooksViewModel.cs @@ -1,4 +1,3 @@ -#nullable enable using System; namespace BTCPayServer.Models.StoreViewModels @@ -11,7 +10,7 @@ namespace BTCPayServer.Models.StoreViewModels public string Url { get; set; } public bool LastDeliverySuccessful { get; set; } = true; public DateTimeOffset? LastDeliveryTimeStamp { get; set; } = null; - public string? LastDeliveryErrorMessage { get; set; } = null; + public string LastDeliveryErrorMessage { get; set; } = null; } public WebhookViewModel[] Webhooks { get; set; } } diff --git a/BTCPayServer/Payments/PayJoin/PayJoinEndpointController.cs b/BTCPayServer/Payments/PayJoin/PayJoinEndpointController.cs index b580a79fb..bc9778a37 100644 --- a/BTCPayServer/Payments/PayJoin/PayJoinEndpointController.cs +++ b/BTCPayServer/Payments/PayJoin/PayJoinEndpointController.cs @@ -462,10 +462,11 @@ namespace BTCPayServer.Payments.PayJoin var coin = selectedUtxo.AsCoin(derivationSchemeSettings.AccountDerivation); signedInput.UpdateFromCoin(coin); var privateKey = accountKey.Derive(selectedUtxo.KeyPath).PrivateKey; - signedInput.Sign(privateKey, new SigningOptions() + signedInput.PSBT.Settings.SigningOptions = new SigningOptions() { EnforceLowR = enforcedLowR - }); + }; + signedInput.Sign(privateKey); signedInput.FinalizeInput(); newTx.Inputs[signedInput.Index].WitScript = newPsbt.Inputs[(int)signedInput.Index].FinalScriptWitness; } diff --git a/BTCPayServer/Services/LanguageService.cs b/BTCPayServer/Services/LanguageService.cs index f02d3264a..da88f25b1 100644 --- a/BTCPayServer/Services/LanguageService.cs +++ b/BTCPayServer/Services/LanguageService.cs @@ -83,7 +83,7 @@ namespace BTCPayServer.Services acceptedLocales[locale] = qualityScore; } } - catch (System.FormatException e) + catch (System.FormatException) { // Can't use this piece, moving on... }