Skip to content

Commit 9cd8b38

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 8be0890 commit 9cd8b38

File tree

1 file changed

+68
-4
lines changed

1 file changed

+68
-4
lines changed

itest/litd_custom_channels_test.go

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ 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"
3132
"github.com/lightningnetwork/lnd/lntest"
3233
"github.com/lightningnetwork/lnd/lntest/node"
3334
"github.com/lightningnetwork/lnd/lntest/port"
@@ -2239,12 +2240,12 @@ func testCustomChannelsBreach(ctx context.Context, net *NetworkHarness,
22392240
t.Logf("Charlie balance after breach: %d", charlieBalance)
22402241
}
22412242

2242-
// testCustomChannelsLiquidtyEdgeCasesCore is the core logic of the liquidity
2243+
// testCustomChannelsLiquidityEdgeCasesCore is the core logic of the liquidity
22432244
// edge cases. This test goes through certain scenarios that expose edge cases
22442245
// and behaviors that proved to be buggy in the past and have been directly
22452246
// addressed. It accepts an extra parameter which dictates whether it should use
22462247
// group keys or asset IDs.
2247-
func testCustomChannelsLiquidtyEdgeCasesCore(ctx context.Context,
2248+
func testCustomChannelsLiquidityEdgeCasesCore(ctx context.Context,
22482249
net *NetworkHarness, t *harnessTest, groupMode bool) {
22492250

22502251
lndArgs := slices.Clone(lndArgsTemplate)
@@ -2742,6 +2743,69 @@ func testCustomChannelsLiquidtyEdgeCasesCore(ctx context.Context,
27422743
)
27432744

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

27472811
// testCustomChannelsLiquidityEdgeCases is a test that runs through some
@@ -2751,7 +2815,7 @@ func testCustomChannelsLiquidityEdgeCases(ctx context.Context,
27512815

27522816
// Run liquidity edge cases and only use single asset IDs for invoices
27532817
// and payments.
2754-
testCustomChannelsLiquidtyEdgeCasesCore(ctx, net, t, false)
2818+
testCustomChannelsLiquidityEdgeCasesCore(ctx, net, t, false)
27552819
}
27562820

27572821
// testCustomChannelsLiquidityEdgeCasesGroup is a test that runs through some
@@ -2761,7 +2825,7 @@ func testCustomChannelsLiquidityEdgeCasesGroup(ctx context.Context,
27612825

27622826
// Run liquidity edge cases and only use group keys for invoices and
27632827
// payments.
2764-
testCustomChannelsLiquidtyEdgeCasesCore(ctx, net, t, true)
2828+
testCustomChannelsLiquidityEdgeCasesCore(ctx, net, t, true)
27652829
}
27662830

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

0 commit comments

Comments
 (0)