Skip to content

Commit b7089fa

Browse files
GeorgeTsagkffranr
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 b7089fa

File tree

1 file changed

+68
-4
lines changed

1 file changed

+68
-4
lines changed

itest/litd_custom_channels_test.go

+68-4
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"
@@ -2220,12 +2221,12 @@ func testCustomChannelsBreach(ctx context.Context, net *NetworkHarness,
22202221
t.Logf("Charlie UTXOs after breach: %v", toProtoJSON(t.t, charlieUTXOs))
22212222
}
22222223

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

22312232
lndArgs := slices.Clone(lndArgsTemplate)
@@ -2723,6 +2724,69 @@ func testCustomChannelsLiquidtyEdgeCasesCore(ctx context.Context,
27232724
)
27242725

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

27282792
// testCustomChannelsLiquidityEdgeCases is a test that runs through some
@@ -2732,7 +2796,7 @@ func testCustomChannelsLiquidityEdgeCases(ctx context.Context,
27322796

27332797
// Run liquidity edge cases and only use single asset IDs for invoices
27342798
// and payments.
2735-
testCustomChannelsLiquidtyEdgeCasesCore(ctx, net, t, false)
2799+
testCustomChannelsLiquidityEdgeCasesCore(ctx, net, t, false)
27362800
}
27372801

27382802
// testCustomChannelsLiquidityEdgeCasesGroup is a test that runs through some
@@ -2742,7 +2806,7 @@ func testCustomChannelsLiquidityEdgeCasesGroup(ctx context.Context,
27422806

27432807
// Run liquidity edge cases and only use group keys for invoices and
27442808
// payments.
2745-
testCustomChannelsLiquidtyEdgeCasesCore(ctx, net, t, true)
2809+
testCustomChannelsLiquidityEdgeCasesCore(ctx, net, t, true)
27462810
}
27472811

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

0 commit comments

Comments
 (0)