From 562f88555c7bbc0b2f1d84a602a40f77aebd255a Mon Sep 17 00:00:00 2001 From: d11n Date: Sat, 5 Nov 2022 12:21:24 +0100 Subject: [PATCH] Lightning: Better handling for non-public nodes (#4263) Fixes #4246. `LightningLikePaymentHandler.GetNodeInfo` needed the `throws` argument to handle the cases as previously, otherwise the catch case in `ShowLightningNodeInfo` never occured. State with this PR: A node can be available, but not have any public addresses. The latter will now be reported when testing the connection and on the public node info page. --- .../UIPublicLightningNodeInfoController.cs | 5 +- .../UIStoresController.LightningLike.cs | 9 ++-- .../Lightning/LightningLikePaymentHandler.cs | 7 +-- .../ShowLightningNodeInfo.cshtml | 53 +++++++++++-------- 4 files changed, 39 insertions(+), 35 deletions(-) diff --git a/BTCPayServer/Controllers/UIPublicLightningNodeInfoController.cs b/BTCPayServer/Controllers/UIPublicLightningNodeInfoController.cs index b7201fe45..e8590ef0d 100644 --- a/BTCPayServer/Controllers/UIPublicLightningNodeInfoController.cs +++ b/BTCPayServer/Controllers/UIPublicLightningNodeInfoController.cs @@ -13,7 +13,6 @@ using Microsoft.AspNetCore.Mvc; namespace BTCPayServer.Controllers { - [Route("embed/{storeId}/{cryptoCode}/ln")] [AllowAnonymous] public class UIPublicLightningNodeInfoController : Controller @@ -43,11 +42,11 @@ namespace BTCPayServer.Controllers var paymentMethodDetails = GetExistingLightningSupportedPaymentMethod(cryptoCode, store); var network = _BtcPayNetworkProvider.GetNetwork(cryptoCode); var nodeInfo = - await _LightningLikePaymentHandler.GetNodeInfo(paymentMethodDetails, network, new InvoiceLogs()); + await _LightningLikePaymentHandler.GetNodeInfo(paymentMethodDetails, network, new InvoiceLogs(), throws: true); return View(new ShowLightningNodeInfoViewModel { - Available = nodeInfo.Any(), + Available = true, NodeInfo = nodeInfo.Select(n => new ShowLightningNodeInfoViewModel.NodeData(n)).ToArray(), CryptoCode = cryptoCode, CryptoImage = GetImage(paymentMethodDetails.PaymentId, network), diff --git a/BTCPayServer/Controllers/UIStoresController.LightningLike.cs b/BTCPayServer/Controllers/UIStoresController.LightningLike.cs index 2f715b229..5d4d5cc96 100644 --- a/BTCPayServer/Controllers/UIStoresController.LightningLike.cs +++ b/BTCPayServer/Controllers/UIStoresController.LightningLike.cs @@ -194,12 +194,15 @@ namespace BTCPayServer.Controllers try { var info = await handler.GetNodeInfo(paymentMethod, network, new InvoiceLogs(), Request.IsOnion(), true); - if (!vm.SkipPortTest) + var hasPublicAddress = info.Any(); + if (!vm.SkipPortTest && hasPublicAddress) { using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(20)); await handler.TestConnection(info.First(), cts.Token); } - TempData[WellKnownTempData.SuccessMessage] = $"Connection to the Lightning node successful. Your node address: {info.First()}"; + TempData[WellKnownTempData.SuccessMessage] = "Connection to the Lightning node successful" + (hasPublicAddress + ? $". Your node address: {info.First()}" + : ", but no public address has been configured"); } catch (Exception ex) { @@ -225,7 +228,7 @@ namespace BTCPayServer.Controllers var lightning = GetExistingLightningSupportedPaymentMethod(cryptoCode, store); if (lightning == null) { - TempData[WellKnownTempData.ErrorMessage] = $"You need to connect to a Lightning node before adjusting its settings."; + TempData[WellKnownTempData.ErrorMessage] = "You need to connect to a Lightning node before adjusting its settings."; return RedirectToAction(nameof(SetupLightningNode), new { storeId, cryptoCode }); } diff --git a/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs b/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs index f7313828b..e376c2c32 100644 --- a/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs +++ b/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs @@ -147,16 +147,11 @@ namespace BTCPayServer.Payments.Lightning (!string.IsNullOrEmpty(ex.InnerException?.Message) ? $" ({ex.InnerException.Message})" : "")); } + // Node info might be empty if there are no public URIs to announce. The UI also supports this. var nodeInfo = preferOnion != null && info.NodeInfoList.Any(i => i.IsTor == preferOnion) ? info.NodeInfoList.Where(i => i.IsTor == preferOnion.Value).ToArray() : info.NodeInfoList.Select(i => i).ToArray(); - // Maybe the user does not have an easily accessible ln node. Node info should be optional. The UI also supports this. - // if (!nodeInfo.Any()) - // { - // throw new PaymentMethodUnavailableException("No lightning node public address has been configured"); - // } - var blocksGap = summary.Status.ChainHeight - info.BlockHeight; if (blocksGap > 10) { diff --git a/BTCPayServer/Views/UIPublicLightningNodeInfo/ShowLightningNodeInfo.cshtml b/BTCPayServer/Views/UIPublicLightningNodeInfo/ShowLightningNodeInfo.cshtml index 2f98740b8..5d5c973ee 100644 --- a/BTCPayServer/Views/UIPublicLightningNodeInfo/ShowLightningNodeInfo.cshtml +++ b/BTCPayServer/Views/UIPublicLightningNodeInfo/ShowLightningNodeInfo.cshtml @@ -28,34 +28,41 @@ @if (Model.Available) { - @if (Model.NodeInfo.Length > 1) + @if (Model.NodeInfo.Any()) { - + + } + else + { +

No public address available.

} -
- @for (var i = 0; i < Model.NodeInfo.Length; i++) - { - var nodeInfo = Model.NodeInfo[i].ToString(); -
-
- @Model.CryptoCode - -
-
- - -
-
- } -
}