From aea9e9d9b384c47278acf7b89c9fae106d7950dd Mon Sep 17 00:00:00 2001 From: "Andres G. Aragoneses" Date: Tue, 6 Oct 2020 17:56:05 +0200 Subject: [PATCH] tests: add a test for closing a channel with LND Not sure if we should add this as the Dispose() method of the test class actually: https://stackoverflow.com/a/33516224/544947 --- .../OpenChannelResponse.cs | 4 +++ src/BTCPayServer.Lightning.LND/LndClient.cs | 4 ++- tests/ChannelSetup.cs | 11 ++++++++ tests/CommonTests.cs | 25 +++++++++++++++++++ tests/Tester.cs | 13 +++++++--- 5 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/BTCPayServer.Lightning.Common/OpenChannelResponse.cs b/src/BTCPayServer.Lightning.Common/OpenChannelResponse.cs index 3a61b822..c72913fa 100644 --- a/src/BTCPayServer.Lightning.Common/OpenChannelResponse.cs +++ b/src/BTCPayServer.Lightning.Common/OpenChannelResponse.cs @@ -23,5 +23,9 @@ public OpenChannelResult Result { get; set; } + public string FundingTxIdIfAvailable + { + get; set; + } } } diff --git a/src/BTCPayServer.Lightning.LND/LndClient.cs b/src/BTCPayServer.Lightning.LND/LndClient.cs index 8d53a348..d1b9da24 100644 --- a/src/BTCPayServer.Lightning.LND/LndClient.cs +++ b/src/BTCPayServer.Lightning.LND/LndClient.cs @@ -373,7 +373,9 @@ async Task ILightningClient.OpenChannel(OpenChannelRequest req.Sat_per_byte = ((int)openChannelRequest.FeeRate.SatoshiPerByte).ToString(); } var result = await this.SwaggerClient.OpenChannelSyncAsync(req, cancellation); - return new OpenChannelResponse(OpenChannelResult.Ok); + var res = new OpenChannelResponse(OpenChannelResult.Ok); + res.FundingTxIdIfAvailable = result.Funding_txid_str; + return res; } catch(SwaggerException ex) when (ex.AsLNDError() is LndError2 lndError && diff --git a/tests/ChannelSetup.cs b/tests/ChannelSetup.cs index c6ac1a10..bb911b29 100644 --- a/tests/ChannelSetup.cs +++ b/tests/ChannelSetup.cs @@ -48,6 +48,15 @@ public static async Task OpenAll(RPCClient cashCow, IEnumerable availableFundingTxIds + = new Dictionary<(ILightningClient, ILightningClient), string>(); + + internal static string GetFundingTxIdForChannel(ILightningClient sender, ILightningClient dest) + { + return availableFundingTxIds.GetValueOrDefault((sender, dest)); + } + public static async Task OpenChannel(RPCClient cashCow, ILightningClient sender, ILightningClient dest) { var destInfo = await dest.GetInfo(); @@ -115,6 +124,8 @@ public static async Task OpenChannel(RPCClient cashCow, ILightningClient sender, } if(openChannel.Result == OpenChannelResult.Ok) { + if (!String.IsNullOrEmpty(openChannel.FundingTxIdIfAvailable)) + availableFundingTxIds[(sender, dest)] = openChannel.FundingTxIdIfAvailable; // generate one block and a bit more time to confirm channel opening await cashCow.GenerateAsync(1); await WaitLNSynched(cashCow, sender); diff --git a/tests/CommonTests.cs b/tests/CommonTests.cs index cb6f52b1..8a81e234 100644 --- a/tests/CommonTests.cs +++ b/tests/CommonTests.cs @@ -536,5 +536,30 @@ public void CanParseLightningURL() Assert.True(LightningConnectionString.TryParse("type=charge;server=http://api-token:foiewnccewuify@127.0.0.1:54938/;allowinsecure=true", out conn)); Assert.Equal("type=charge;server=http://127.0.0.1:54938/;api-token=foiewnccewuify;allowinsecure=true", conn.ToString()); } + + [Fact(Timeout = Timeout)] + public async Task CanCloseLndChannel() + { + // TODO: test in all LN implementations, not just LND + //foreach (var test in Tester.GetTestedPairs()) + //{ + var test = Tester.GetTestedLndPair(); + await EnsureConnectedToDestinations(test); + var customer = (ILightningClient)test.Customer; + var senderChannel = (await customer.ListChannels()).First(); + + var senderInfo = await customer.GetInfo(); + var fundingTxIdForChannel = ChannelSetup.GetFundingTxIdForChannel(customer, test.Merchant); + if (String.IsNullOrEmpty(fundingTxIdForChannel)) + throw new InvalidOperationException("Could not find funding Tx ID of channel"); + var closeChannelRequest = new CloseChannelRequest() + { + NodeInfo = senderInfo.NodeInfoList.First(), + ChannelPointOutputIndex = senderChannel.ChannelPoint.N, + ChannelPointFundingTxIdStr = fundingTxIdForChannel + }; + await test.Merchant.CloseChannel(closeChannelRequest, CancellationToken.None); + //} + } } } diff --git a/tests/Tester.cs b/tests/Tester.cs index 8d983523..5ee69295 100644 --- a/tests/Tester.cs +++ b/tests/Tester.cs @@ -87,11 +87,18 @@ public static LndClient CreateLndClientDest() yield return ("Eclair (Client)", CreateEclairClient()); } + private static (string Name, ILightningClient Customer, ILightningClient Merchant) GetTestedCLightningPair() + => ("C-Lightning", CreateCLightningClient(), CreateCLightningClientDest()); + internal static (string Name, LndClient Customer, LndClient Merchant) GetTestedLndPair() + => ("LND", CreateLndClient(), CreateLndClientDest()); + private static (string Name, ILightningClient Customer, ILightningClient Merchant) GetTestedEclairPair() + => ("Eclair", CreateEclairClient(), CreateEclairClientDest()); + public static IEnumerable<(string Name, ILightningClient Customer, ILightningClient Merchant)> GetTestedPairs() { - yield return ("C-Lightning", CreateCLightningClient(), CreateCLightningClientDest()); - yield return ("LND", CreateLndClient(), CreateLndClientDest()); - yield return ("Eclair", CreateEclairClient(), CreateEclairClientDest()); + yield return GetTestedCLightningPair(); + yield return GetTestedLndPair(); + yield return GetTestedEclairPair(); } } }