Skip to content

Commit 3294e30

Browse files
committed
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 1a7c249 commit 3294e30

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
@@ -30,6 +30,7 @@ import (
3030
"github.com/lightningnetwork/lnd/fn"
3131
"github.com/lightningnetwork/lnd/lnrpc"
3232
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
33+
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
3334
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
3435
"github.com/lightningnetwork/lnd/lntest"
3536
"github.com/lightningnetwork/lnd/lntest/node"
@@ -2601,12 +2602,12 @@ func testCustomChannelsBreach(ctx context.Context, net *NetworkHarness,
26012602
t.Logf("Charlie UTXOs after breach: %v", toProtoJSON(t.t, charlieUTXOs))
26022603
}
26032604

2604-
// testCustomChannelsLiquidtyEdgeCasesCore is the core logic of the liquidity
2605+
// testCustomChannelsLiquidityEdgeCasesCore is the core logic of the liquidity
26052606
// edge cases. This test goes through certain scenarios that expose edge cases
26062607
// and behaviors that proved to be buggy in the past and have been directly
26072608
// addressed. It accepts an extra parameter which dictates whether it should use
26082609
// group keys or asset IDs.
2609-
func testCustomChannelsLiquidtyEdgeCasesCore(ctx context.Context,
2610+
func testCustomChannelsLiquidityEdgeCasesCore(ctx context.Context,
26102611
net *NetworkHarness, t *harnessTest, groupMode bool) {
26112612

26122613
lndArgs := slices.Clone(lndArgsTemplate)
@@ -3104,6 +3105,69 @@ func testCustomChannelsLiquidtyEdgeCasesCore(ctx context.Context,
31043105
)
31053106

31063107
logBalance(t.t, nodes, assetID, "after small manual rfq")
3108+
3109+
// Edge case: Fabia creates an invoice which Erin cannot satisfy with
3110+
// his side of asset liquidity. This tests that Erin will not try to
3111+
// add an HTLC with more asset units than what his local balance is. To
3112+
// validate that the channel is still healthy, we follow up with a
3113+
// smaller invoice payment which is meant to succeed.
3114+
3115+
// We now create a hodl invoice on Fabia, for 125k assets.
3116+
hodlInv = createAssetHodlInvoice(t.t, erin, fabia, 125_000, assetID)
3117+
3118+
htlcStream, err := erin.RouterClient.SubscribeHtlcEvents(
3119+
ctx, &routerrpc.SubscribeHtlcEventsRequest{},
3120+
)
3121+
require.NoError(t.t, err)
3122+
3123+
// Charlie tries to pay, this is not meant to succeed, as Erin does not
3124+
// have enough assets to forward to Fabia.
3125+
payInvoiceWithAssets(
3126+
t.t, charlie, dave, hodlInv.payReq, assetID,
3127+
withFailure(lnrpc.Payment_IN_FLIGHT, failureNone),
3128+
)
3129+
3130+
// Let's check that at least 2 HTLCs were added on the Erin->Fabia link,
3131+
// which means that Erin would have an extra incoming HTLC for each
3132+
// outgoing one. So we expect a minimum of 4 HTLCs present on Erin.
3133+
assertMinNumHtlcs(t.t, erin, 4)
3134+
3135+
// We also want to make sure that at least one failure occurred that
3136+
// hinted at the problem (not enough assets to forward).
3137+
assertHtlcEvents(
3138+
t.t, htlcStream, withNumEvents(1),
3139+
withLinkFailure(routerrpc.FailureDetail_INSUFFICIENT_BALANCE),
3140+
)
3141+
3142+
logBalance(t.t, nodes, assetID, "with min 4 present HTLCs")
3143+
3144+
// Now Fabia cancels the invoice, this is meant to cancel back any
3145+
// locked in HTLCs and reset Erin's local balance back to its original
3146+
// value.
3147+
payHash = hodlInv.preimage.Hash()
3148+
_, err = fabia.InvoicesClient.CancelInvoice(
3149+
ctx, &invoicesrpc.CancelInvoiceMsg{
3150+
PaymentHash: payHash[:],
3151+
},
3152+
)
3153+
require.NoError(t.t, err)
3154+
3155+
// Let's assert that Erin cancelled all his HTLCs.
3156+
assertNumHtlcs(t.t, erin, 0)
3157+
3158+
logBalance(t.t, nodes, assetID, "after hodl cancel & 0 present HTLCs")
3159+
3160+
// Now let's create a smaller invoice and pay it, to validate that the
3161+
// channel is still healthy.
3162+
invoiceResp = createAssetInvoice(
3163+
t.t, erin, fabia, 50_000, assetID,
3164+
)
3165+
3166+
payInvoiceWithAssets(
3167+
t.t, charlie, dave, invoiceResp.PaymentRequest, assetID,
3168+
)
3169+
3170+
logBalance(t.t, nodes, assetID, "after safe asset htlc failure")
31073171
}
31083172

31093173
// testCustomChannelsLiquidityEdgeCases is a test that runs through some
@@ -3113,7 +3177,7 @@ func testCustomChannelsLiquidityEdgeCases(ctx context.Context,
31133177

31143178
// Run liquidity edge cases and only use single asset IDs for invoices
31153179
// and payments.
3116-
testCustomChannelsLiquidtyEdgeCasesCore(ctx, net, t, false)
3180+
testCustomChannelsLiquidityEdgeCasesCore(ctx, net, t, false)
31173181
}
31183182

31193183
// testCustomChannelsLiquidityEdgeCasesGroup is a test that runs through some
@@ -3123,7 +3187,7 @@ func testCustomChannelsLiquidityEdgeCasesGroup(ctx context.Context,
31233187

31243188
// Run liquidity edge cases and only use group keys for invoices and
31253189
// payments.
3126-
testCustomChannelsLiquidtyEdgeCasesCore(ctx, net, t, true)
3190+
testCustomChannelsLiquidityEdgeCasesCore(ctx, net, t, true)
31273191
}
31283192

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

0 commit comments

Comments
 (0)