mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-19 06:54:19 +01:00
Simplify LND implementation
This commit is contained in:
@@ -15,12 +15,12 @@ namespace BTCPayServer.Tests.Lnd
|
|||||||
this._Parent = serverTester;
|
this._Parent = serverTester;
|
||||||
var url = serverTester.GetEnvironment(environmentName, defaultValue);
|
var url = serverTester.GetEnvironment(environmentName, defaultValue);
|
||||||
|
|
||||||
Swagger = LndSwaggerClientCustomHttp.Create(new Uri(url), network);
|
Swagger = new LndSwaggerClient(new LndRestSettings(new Uri(url)));
|
||||||
Client = new LndInvoiceClient(Swagger);
|
Client = new LndInvoiceClient(Swagger);
|
||||||
P2PHost = _Parent.GetEnvironment(environmentName + "_HOST", defaultHost);
|
P2PHost = _Parent.GetEnvironment(environmentName + "_HOST", defaultHost);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LndSwaggerClientCustomHttp Swagger { get; set; }
|
public LndSwaggerClient Swagger { get; set; }
|
||||||
public LndInvoiceClient Client { get; set; }
|
public LndInvoiceClient Client { get; set; }
|
||||||
public string P2PHost { get; }
|
public string P2PHost { get; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,16 +25,16 @@ namespace BTCPayServer.Tests.Lnd
|
|||||||
this.output = output;
|
this.output = output;
|
||||||
initializeEnvironment();
|
initializeEnvironment();
|
||||||
|
|
||||||
MerchantLnd = LndSwaggerClientCustomHttp.Create(new Uri("http://127.0.0.1:53280"), Network.RegTest);
|
MerchantLnd = new LndSwaggerClient(new LndRestSettings(new Uri("http://127.0.0.1:53280")));
|
||||||
InvoiceClient = new LndInvoiceClient(MerchantLnd);
|
InvoiceClient = new LndInvoiceClient(MerchantLnd);
|
||||||
|
|
||||||
CustomerLnd = LndSwaggerClientCustomHttp.Create(new Uri("http://127.0.0.1:53281"), Network.RegTest);
|
CustomerLnd = new LndSwaggerClient(new LndRestSettings(new Uri("http://127.0.0.1:53281")));
|
||||||
}
|
}
|
||||||
|
|
||||||
private LndSwaggerClientCustomHttp MerchantLnd { get; set; }
|
private LndSwaggerClient MerchantLnd { get; set; }
|
||||||
private LndInvoiceClient InvoiceClient { get; set; }
|
private LndInvoiceClient InvoiceClient { get; set; }
|
||||||
|
|
||||||
private LndSwaggerClientCustomHttp CustomerLnd { get; set; }
|
private LndSwaggerClient CustomerLnd { get; set; }
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task GetInfo()
|
public async Task GetInfo()
|
||||||
|
|||||||
@@ -521,7 +521,7 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.Equal(lndUri, conn.ToString());
|
Assert.Equal(lndUri, conn.ToString());
|
||||||
Assert.Equal(LightningConnectionType.LndREST, conn.ConnectionType);
|
Assert.Equal(LightningConnectionType.LndREST, conn.ConnectionType);
|
||||||
Assert.Equal(macaroon, Encoders.Hex.EncodeData(conn.Macaroon));
|
Assert.Equal(macaroon, Encoders.Hex.EncodeData(conn.Macaroon));
|
||||||
Assert.Equal(tls, Encoders.Hex.EncodeData(conn.Tls));
|
Assert.Equal(tls, Encoders.Hex.EncodeData(conn.Tls.RawData));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
@@ -30,8 +30,11 @@ namespace BTCPayServer.Payments.Lightning
|
|||||||
}
|
}
|
||||||
else if (connString.ConnectionType == LightningConnectionType.LndREST)
|
else if (connString.ConnectionType == LightningConnectionType.LndREST)
|
||||||
{
|
{
|
||||||
var swagger = LndSwaggerClientCustomHttp.Create(connString.BaseUri, network, connString.Tls, connString.Macaroon);
|
return new LndInvoiceClient(new LndSwaggerClient(new LndRestSettings(connString.BaseUri)
|
||||||
return new LndInvoiceClient(swagger);
|
{
|
||||||
|
Macaroon = connString.Macaroon,
|
||||||
|
TLS = connString.Tls
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw new NotSupportedException($"Unsupported connection string for lightning server ({connString.ConnectionType})");
|
throw new NotSupportedException($"Unsupported connection string for lightning server ({connString.ConnectionType})");
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
@@ -197,11 +198,11 @@ namespace BTCPayServer.Payments.Lightning
|
|||||||
{
|
{
|
||||||
var tls = Take(keyValues, "tls");
|
var tls = Take(keyValues, "tls");
|
||||||
if (tls != null)
|
if (tls != null)
|
||||||
result.Tls = Encoder.DecodeData(tls);
|
result.Tls = new X509Certificate2(Encoder.DecodeData(tls));
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
error = $"The key 'tls' format should be in hex";
|
error = $"The key 'tls' should be the X509 certificate in hex";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -301,7 +302,7 @@ namespace BTCPayServer.Payments.Lightning
|
|||||||
private set;
|
private set;
|
||||||
}
|
}
|
||||||
public byte[] Macaroon { get; set; }
|
public byte[] Macaroon { get; set; }
|
||||||
public byte[] Tls { get; set; }
|
public X509Certificate2 Tls { get; set; }
|
||||||
|
|
||||||
public Uri ToUri(bool withCredentials)
|
public Uri ToUri(bool withCredentials)
|
||||||
{
|
{
|
||||||
@@ -350,7 +351,7 @@ namespace BTCPayServer.Payments.Lightning
|
|||||||
}
|
}
|
||||||
if (Tls != null)
|
if (Tls != null)
|
||||||
{
|
{
|
||||||
builder.Append($";tls={Encoder.EncodeData(Tls)}");
|
builder.Append($";tls={Encoder.EncodeData(Tls.RawData)}");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -19,9 +19,11 @@ namespace BTCPayServer.Payments.Lightning.Lnd
|
|||||||
{
|
{
|
||||||
public LndSwaggerClient _rpcClient;
|
public LndSwaggerClient _rpcClient;
|
||||||
|
|
||||||
public LndInvoiceClient(LndSwaggerClient rpcClient)
|
public LndInvoiceClient(LndSwaggerClient swaggerClient)
|
||||||
{
|
{
|
||||||
_rpcClient = rpcClient;
|
if (swaggerClient == null)
|
||||||
|
throw new ArgumentNullException(nameof(swaggerClient));
|
||||||
|
_rpcClient = swaggerClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<LightningInvoice> CreateInvoice(LightMoney amount, string description, TimeSpan expiry,
|
public async Task<LightningInvoice> CreateInvoice(LightMoney amount, string description, TimeSpan expiry,
|
||||||
|
|||||||
@@ -16,102 +16,53 @@ using Newtonsoft.Json.Linq;
|
|||||||
|
|
||||||
namespace BTCPayServer.Payments.Lightning.Lnd
|
namespace BTCPayServer.Payments.Lightning.Lnd
|
||||||
{
|
{
|
||||||
public class LndSwaggerClientCustomHttp : LndSwaggerClient, IDisposable
|
public class LndRestSettings
|
||||||
{
|
{
|
||||||
protected LndSwaggerClientCustomHttp(string baseUrl, HttpClient httpClient)
|
public LndRestSettings()
|
||||||
: base(baseUrl, httpClient)
|
|
||||||
{
|
{
|
||||||
_HttpClient = httpClient;
|
|
||||||
}
|
}
|
||||||
|
public LndRestSettings(Uri uri)
|
||||||
private HttpClient _HttpClient;
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
{
|
||||||
_HttpClient.Dispose();
|
Uri = uri;
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
public static LndSwaggerClientCustomHttp Create(Uri uri, Network network, byte[] tlsCertificate = null, byte[] grpcMacaroon = null)
|
|
||||||
{
|
|
||||||
var factory = new HttpClientFactoryForLnd(tlsCertificate, grpcMacaroon);
|
|
||||||
var httpClient = factory.Generate();
|
|
||||||
|
|
||||||
var swagger = new LndSwaggerClientCustomHttp(uri.ToString().TrimEnd('/'), httpClient);
|
|
||||||
swagger.HttpClientFactory = factory;
|
|
||||||
|
|
||||||
return swagger;
|
|
||||||
}
|
}
|
||||||
|
public Uri Uri { get; set; }
|
||||||
|
public X509Certificate2 TLS { get; set; }
|
||||||
|
public byte[] Macaroon { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class HttpClientFactoryForLnd
|
public partial class LndSwaggerClient
|
||||||
{
|
{
|
||||||
public HttpClientFactoryForLnd(byte[] tlsCertificate = null, byte[] grpcMacaroon = null)
|
public LndSwaggerClient(LndRestSettings settings)
|
||||||
|
: this(settings.Uri.AbsoluteUri.TrimEnd('/'), CreateHttpClient(settings))
|
||||||
{
|
{
|
||||||
TlsCertificate = tlsCertificate;
|
_Settings = settings;
|
||||||
GrpcMacaroon = grpcMacaroon;
|
|
||||||
}
|
}
|
||||||
|
LndRestSettings _Settings;
|
||||||
public byte[] TlsCertificate { get; set; }
|
private static HttpClient CreateHttpClient(LndRestSettings settings)
|
||||||
public byte[] GrpcMacaroon { get; set; }
|
|
||||||
|
|
||||||
public HttpClient Generate()
|
|
||||||
{
|
|
||||||
var httpClient = new HttpClient(GetCertificate(TlsCertificate));
|
|
||||||
|
|
||||||
if (GrpcMacaroon != null)
|
|
||||||
{
|
|
||||||
var macaroonHex = BitConverter.ToString(GrpcMacaroon).Replace("-", "", StringComparison.InvariantCulture);
|
|
||||||
httpClient.DefaultRequestHeaders.Add("Grpc-Metadata-macaroon", macaroonHex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return httpClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static HttpClientHandler GetCertificate(byte[] certFile)
|
|
||||||
{
|
{
|
||||||
var handler = new HttpClientHandler
|
var handler = new HttpClientHandler
|
||||||
{
|
{
|
||||||
SslProtocols = SslProtocols.Tls12
|
SslProtocols = SslProtocols.Tls12
|
||||||
};
|
};
|
||||||
if (certFile == null)
|
|
||||||
|
var expectedCertificate = settings.TLS;
|
||||||
|
if (expectedCertificate != null)
|
||||||
{
|
{
|
||||||
handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
|
handler.ServerCertificateCustomValidationCallback = (request, cert, chain, errors) =>
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if certificate is not null, try with custom accepting logic
|
|
||||||
X509Certificate2 clientCertificate = null;
|
|
||||||
if (certFile != null)
|
|
||||||
clientCertificate = new X509Certificate2(certFile);
|
|
||||||
|
|
||||||
handler.ServerCertificateCustomValidationCallback = (request, cert, chain, errors) =>
|
|
||||||
{
|
|
||||||
const SslPolicyErrors unforgivableErrors =
|
|
||||||
SslPolicyErrors.RemoteCertificateNotAvailable |
|
|
||||||
SslPolicyErrors.RemoteCertificateNameMismatch;
|
|
||||||
|
|
||||||
if ((errors & unforgivableErrors) != 0)
|
|
||||||
{
|
{
|
||||||
return false;
|
X509Certificate2 remoteRoot = chain.ChainElements[chain.ChainElements.Count - 1].Certificate;
|
||||||
}
|
return expectedCertificate.RawData.SequenceEqual(remoteRoot.RawData);
|
||||||
|
};
|
||||||
if (clientCertificate == null)
|
}
|
||||||
return true;
|
var httpClient = new HttpClient(handler);
|
||||||
|
if (settings.Macaroon != null)
|
||||||
X509Certificate2 remoteRoot = chain.ChainElements[chain.ChainElements.Count - 1].Certificate;
|
{
|
||||||
var res = clientCertificate.RawData.SequenceEqual(remoteRoot.RawData);
|
var macaroonHex = BitConverter.ToString(settings.Macaroon).Replace("-", "", StringComparison.InvariantCulture);
|
||||||
|
httpClient.DefaultRequestHeaders.Add("Grpc-Metadata-macaroon", macaroonHex);
|
||||||
return res;
|
}
|
||||||
};
|
return httpClient;
|
||||||
|
|
||||||
return handler;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public partial class LndSwaggerClient
|
|
||||||
{
|
|
||||||
internal HttpClientFactoryForLnd HttpClientFactory { get; set; }
|
|
||||||
|
|
||||||
public TaskCompletionSource<LnrpcInvoice> InvoiceResponse = new TaskCompletionSource<LnrpcInvoice>();
|
public TaskCompletionSource<LnrpcInvoice> InvoiceResponse = new TaskCompletionSource<LnrpcInvoice>();
|
||||||
public TaskCompletionSource<LndSwaggerClient> SubscribeLost = new TaskCompletionSource<LndSwaggerClient>();
|
public TaskCompletionSource<LndSwaggerClient> SubscribeLost = new TaskCompletionSource<LndSwaggerClient>();
|
||||||
@@ -122,7 +73,7 @@ namespace BTCPayServer.Payments.Lightning.Lnd
|
|||||||
var urlBuilder = new StringBuilder();
|
var urlBuilder = new StringBuilder();
|
||||||
urlBuilder.Append(BaseUrl).Append("/v1/invoices/subscribe");
|
urlBuilder.Append(BaseUrl).Append("/v1/invoices/subscribe");
|
||||||
|
|
||||||
using (var client = HttpClientFactory.Generate())
|
using (var client = CreateHttpClient(_Settings))
|
||||||
{
|
{
|
||||||
client.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite);
|
client.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite);
|
||||||
|
|
||||||
Reference in New Issue
Block a user