Greenfield: Graceful return for in-flight HTLCs (#4252)

* Greenfield: Graceful return for in-flight HTLCs

Based on btcpayserver/BTCPayServer.Lightning#106 this closes #3781.

* Update descriptions
This commit is contained in:
d11n 2022-11-02 13:03:34 +01:00 committed by GitHub
parent 05232414ad
commit e56cbf0baa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 63 additions and 12 deletions

View file

@ -28,7 +28,7 @@
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.3.13" />
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.3.15" />
<PackageReference Include="NBitcoin" Version="7.0.14" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>

View file

@ -1,3 +1,4 @@
using System;
using BTCPayServer.Client.JsonConverters;
using BTCPayServer.JsonConverters;
using BTCPayServer.Lightning;
@ -19,5 +20,8 @@ namespace BTCPayServer.Client.Models
[JsonConverter(typeof(LightMoneyJsonConverter))]
public LightMoney Amount { get; set; }
[JsonConverter(typeof(TimeSpanJsonConverter.Seconds))]
public TimeSpan? SendTimeout { get; set; }
}
}

View file

@ -41,7 +41,7 @@
<ItemGroup>
<PackageReference Include="BIP78.Sender" Version="0.2.2" />
<PackageReference Include="BTCPayServer.Hwi" Version="2.0.2" />
<PackageReference Include="BTCPayServer.Lightning.All" Version="1.4.7" />
<PackageReference Include="BTCPayServer.Lightning.All" Version="1.4.8" />
<PackageReference Include="CsvHelper" Version="15.0.5" />
<PackageReference Include="Dapper" Version="2.0.123" />
<PackageReference Include="Fido2" Version="2.0.2" />

View file

@ -2,7 +2,6 @@ using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Abstractions.Contracts;
using BTCPayServer.Abstractions.Extensions;
using BTCPayServer.Client;
using BTCPayServer.Client.Models;
@ -222,16 +221,26 @@ namespace BTCPayServer.Controllers.Greenfield
return this.CreateValidationError(ModelState);
}
var param = lightningInvoice.MaxFeeFlat != null || lightningInvoice.MaxFeePercent != null || lightningInvoice.Amount != null
? new PayInvoiceParams { MaxFeePercent = lightningInvoice.MaxFeePercent, MaxFeeFlat = lightningInvoice.MaxFeeFlat, Amount = lightningInvoice.Amount }
var param = lightningInvoice.MaxFeeFlat != null || lightningInvoice.MaxFeePercent != null
|| lightningInvoice.Amount != null || lightningInvoice.SendTimeout != null
? new PayInvoiceParams
{
MaxFeePercent = lightningInvoice.MaxFeePercent,
MaxFeeFlat = lightningInvoice.MaxFeeFlat,
Amount = lightningInvoice.Amount,
SendTimeout = lightningInvoice.SendTimeout
}
: null;
var result = await lightningClient.Pay(lightningInvoice.BOLT11, param, cancellationToken);
if (result.Result == PayResult.Ok && bolt11?.PaymentHash is not null)
if (result.Result is PayResult.Ok or PayResult.Unknown && bolt11?.PaymentHash is not null)
{
// get a new instance of the LN client, because the old one might have disposed its HTTPClient
lightningClient = await GetLightningClient(cryptoCode, true);
var paymentHash = bolt11.PaymentHash.ToString();
var payment = await lightningClient.GetPayment(paymentHash, cancellationToken);
return Ok(new LightningPaymentData
var data = new LightningPaymentData
{
Id = payment.Id,
PaymentHash = paymentHash,
@ -241,19 +250,25 @@ namespace BTCPayServer.Controllers.Greenfield
CreatedAt = payment.CreatedAt,
TotalAmount = payment.AmountSent,
FeeAmount = payment.Fee,
});
};
return result.Result is PayResult.Ok ? Ok(data) : Accepted(data);
}
return result.Result switch
{
PayResult.CouldNotFindRoute => this.CreateAPIError("could-not-find-route", "Impossible to find a route to the peer"),
PayResult.Error => this.CreateAPIError("generic-error", result.ErrorDetail),
PayResult.Unknown => Accepted(new LightningPaymentData
{
Status = LightningPaymentStatus.Unknown
}),
PayResult.Ok => Ok(new LightningPaymentData
{
Status = LightningPaymentStatus.Complete,
TotalAmount = result.Details?.TotalAmount,
FeeAmount = result.Details?.FeeAmount
}),
_ => throw new NotSupportedException("Unsupported Payresult")
_ => throw new NotSupportedException("Unsupported PayResult")
};
}

View file

@ -281,6 +281,8 @@ namespace BTCPayServer.Data.Payouts.LightningLike
var proofBlob = new PayoutLightningBlob() {PaymentHash = bolt11PaymentRequest.PaymentHash.ToString()};
try
{
// TODO: Incorporate the changes from this PR here:
// https://github.com/btcpayserver/BTCPayServer.Lightning/pull/106
using var cts = new CancellationTokenSource(SendTimeout);
var result = await lightningClient.Pay(bolt11PaymentRequest.ToString(),
new PayInvoiceParams()

View file

@ -100,7 +100,6 @@
},
"TimeSpanSeconds": {
"allOf": [ { "$ref": "#/components/schemas/TimeSpan" } ],
"format": "seconds",
"description": "A span of times in seconds"
},

View file

@ -323,6 +323,17 @@
"nullable": true,
"description": "The fee limit expressed as a fixed amount in satoshi",
"example": "21"
},
"sendTimeout": {
"nullable": true,
"example": 30,
"default": 30,
"description": "The number of seconds after which the payment times out",
"allOf": [
{
"$ref": "#/components/schemas/TimeSpanSeconds"
}
]
}
}
},

View file

@ -465,7 +465,7 @@
"example": "BTC"
}
],
"description": "Pay a lightning invoice.",
"description": "Pay a lightning invoice. In case the payment response times out, the status will be reported as pending and the final status can be resolved using the [Get payment](#operation/InternalLightningNodeApi_GetPayment) endpoint. The default wait time for payment responses is 30 seconds — it might take longer if multiple routes are tried or a hold invoice is getting paid.",
"operationId": "InternalLightningNodeApi_PayInvoice",
"responses": {
"200": {
@ -478,6 +478,16 @@
}
}
},
"202": {
"description": "Payment initiated",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LightningPaymentData"
}
}
}
},
"422": {
"description": "Unable to validate the request",
"content": {

View file

@ -548,7 +548,7 @@
}
}
],
"description": "Pay a lightning invoice.",
"description": "Pay a lightning invoice. In case the payment response times out, the status will be reported as pending and the final status can be resolved using the [Get payment](#operation/StoreLightningNodeApi_GetPayment) endpoint. The default wait time for payment responses is 30 seconds — it might take longer if multiple routes are tried or a hold invoice is getting paid.",
"operationId": "StoreLightningNodeApi_PayInvoice",
"responses": {
"200": {
@ -561,6 +561,16 @@
}
}
},
"202": {
"description": "Payment initiated",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LightningPaymentData"
}
}
}
},
"422": {
"description": "Unable to validate the request",
"content": {