Skip to content

Commit 15c2e98

Browse files
GeorgeTsagkguggero
authored andcommitted
itest: add safe HTLC failure edge case for custom channels
We enhance the liquidity edge cases itest with a new case which makes a payment attempt over a last-hop that uses assets, and does not have sufficient asset liquidity. The healthy expectation is for the HTLCs to be added, as there exists partial liquidity, but they should eventually fail. As a sanity check we then end things with a small payment that can succeed, and assert its completion.
1 parent 6dc82ce commit 15c2e98

File tree

1 file changed

+69
-4
lines changed

1 file changed

+69
-4
lines changed

itest/litd_custom_channels_test.go

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import (
2828
"github.com/lightningnetwork/lnd/fn"
2929
"github.com/lightningnetwork/lnd/lnrpc"
3030
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
31+
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
32+
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
3133
"github.com/lightningnetwork/lnd/lntest"
3234
"github.com/lightningnetwork/lnd/lntest/node"
3335
"github.com/lightningnetwork/lnd/lntest/port"
@@ -2220,12 +2222,12 @@ func testCustomChannelsBreach(ctx context.Context, net *NetworkHarness,
22202222
t.Logf("Charlie UTXOs after breach: %v", toProtoJSON(t.t, charlieUTXOs))
22212223
}
22222224

2223-
// testCustomChannelsLiquidtyEdgeCasesCore is the core logic of the liquidity
2225+
// testCustomChannelsLiquidityEdgeCasesCore is the core logic of the liquidity
22242226
// edge cases. This test goes through certain scenarios that expose edge cases
22252227
// and behaviors that proved to be buggy in the past and have been directly
22262228
// addressed. It accepts an extra parameter which dictates whether it should use
22272229
// group keys or asset IDs.
2228-
func testCustomChannelsLiquidtyEdgeCasesCore(ctx context.Context,
2230+
func testCustomChannelsLiquidityEdgeCasesCore(ctx context.Context,
22292231
net *NetworkHarness, t *harnessTest, groupMode bool) {
22302232

22312233
lndArgs := slices.Clone(lndArgsTemplate)
@@ -2723,6 +2725,69 @@ func testCustomChannelsLiquidtyEdgeCasesCore(ctx context.Context,
27232725
)
27242726

27252727
logBalance(t.t, nodes, assetID, "after small manual rfq")
2728+
2729+
// Edge case: Fabia creates an invoice which Erin cannot satisfy with
2730+
// his side of asset liquidity. This tests that Erin will not try to
2731+
// add an HTLC with more asset units than what his local balance is. To
2732+
// validate that the channel is still healthy, we follow up with a
2733+
// smaller invoice payment which is meant to succeed.
2734+
2735+
// We now create a hodl invoice on Fabia, for 125k assets.
2736+
hodlInv = createAssetHodlInvoice(t.t, erin, fabia, 125_000, assetID)
2737+
2738+
htlcStream, err := erin.RouterClient.SubscribeHtlcEvents(
2739+
ctx, &routerrpc.SubscribeHtlcEventsRequest{},
2740+
)
2741+
require.NoError(t.t, err)
2742+
2743+
// Charlie tries to pay, this is not meant to succeed, as Erin does not
2744+
// have enough assets to forward to Fabia.
2745+
payInvoiceWithAssets(
2746+
t.t, charlie, dave, hodlInv.payReq, assetID,
2747+
withFailure(lnrpc.Payment_IN_FLIGHT, failureNone),
2748+
)
2749+
2750+
// Let's check that at least 2 HTLCs were added on the Erin->Fabia link,
2751+
// which means that Erin would have an extra incoming HTLC for each
2752+
// outgoing one. So we expect a minimum of 4 HTLCs present on Erin.
2753+
assertMinNumHtlcs(t.t, erin, 4)
2754+
2755+
// We also want to make sure that at least one failure occurred that
2756+
// hinted at the problem (not enough assets to forward).
2757+
assertHtlcEvents(
2758+
t.t, htlcStream, withNumEvents(1),
2759+
withLinkFailure(routerrpc.FailureDetail_INSUFFICIENT_BALANCE),
2760+
)
2761+
2762+
logBalance(t.t, nodes, assetID, "with min 4 present HTLCs")
2763+
2764+
// Now Fabia cancels the invoice, this is meant to cancel back any
2765+
// locked in HTLCs and reset Erin's local balance back to its original
2766+
// value.
2767+
payHash = hodlInv.preimage.Hash()
2768+
_, err = fabia.InvoicesClient.CancelInvoice(
2769+
ctx, &invoicesrpc.CancelInvoiceMsg{
2770+
PaymentHash: payHash[:],
2771+
},
2772+
)
2773+
require.NoError(t.t, err)
2774+
2775+
// Let's assert that Erin cancelled all his HTLCs.
2776+
assertNumHtlcs(t.t, erin, 0)
2777+
2778+
logBalance(t.t, nodes, assetID, "after hodl cancel & 0 present HTLCs")
2779+
2780+
// Now let's create a smaller invoice and pay it, to validate that the
2781+
// channel is still healthy.
2782+
invoiceResp = createAssetInvoice(
2783+
t.t, erin, fabia, 50_000, assetID,
2784+
)
2785+
2786+
payInvoiceWithAssets(
2787+
t.t, charlie, dave, invoiceResp.PaymentRequest, assetID,
2788+
)
2789+
2790+
logBalance(t.t, nodes, assetID, "after safe asset htlc failure")
27262791
}
27272792

27282793
// testCustomChannelsLiquidityEdgeCases is a test that runs through some
@@ -2732,7 +2797,7 @@ func testCustomChannelsLiquidityEdgeCases(ctx context.Context,
27322797

27332798
// Run liquidity edge cases and only use single asset IDs for invoices
27342799
// and payments.
2735-
testCustomChannelsLiquidtyEdgeCasesCore(ctx, net, t, false)
2800+
testCustomChannelsLiquidityEdgeCasesCore(ctx, net, t, false)
27362801
}
27372802

27382803
// testCustomChannelsLiquidityEdgeCasesGroup is a test that runs through some
@@ -2742,7 +2807,7 @@ func testCustomChannelsLiquidityEdgeCasesGroup(ctx context.Context,
27422807

27432808
// Run liquidity edge cases and only use group keys for invoices and
27442809
// payments.
2745-
testCustomChannelsLiquidtyEdgeCasesCore(ctx, net, t, true)
2810+
testCustomChannelsLiquidityEdgeCasesCore(ctx, net, t, true)
27462811
}
27472812

27482813
// testCustomChannelsStrictForwarding is a test that tests the strict forwarding

0 commit comments

Comments
 (0)