@@ -28,6 +28,7 @@ import (
28
28
"github.com/lightningnetwork/lnd/fn"
29
29
"github.com/lightningnetwork/lnd/lnrpc"
30
30
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
31
+ "github.com/lightningnetwork/lnd/lnrpc/routerrpc"
31
32
"github.com/lightningnetwork/lnd/lntest"
32
33
"github.com/lightningnetwork/lnd/lntest/node"
33
34
"github.com/lightningnetwork/lnd/lntest/port"
@@ -2239,12 +2240,12 @@ func testCustomChannelsBreach(ctx context.Context, net *NetworkHarness,
2239
2240
t .Logf ("Charlie balance after breach: %d" , charlieBalance )
2240
2241
}
2241
2242
2242
- // testCustomChannelsLiquidtyEdgeCasesCore is the core logic of the liquidity
2243
+ // testCustomChannelsLiquidityEdgeCasesCore is the core logic of the liquidity
2243
2244
// edge cases. This test goes through certain scenarios that expose edge cases
2244
2245
// and behaviors that proved to be buggy in the past and have been directly
2245
2246
// addressed. It accepts an extra parameter which dictates whether it should use
2246
2247
// group keys or asset IDs.
2247
- func testCustomChannelsLiquidtyEdgeCasesCore (ctx context.Context ,
2248
+ func testCustomChannelsLiquidityEdgeCasesCore (ctx context.Context ,
2248
2249
net * NetworkHarness , t * harnessTest , groupMode bool ) {
2249
2250
2250
2251
lndArgs := slices .Clone (lndArgsTemplate )
@@ -2742,6 +2743,69 @@ func testCustomChannelsLiquidtyEdgeCasesCore(ctx context.Context,
2742
2743
)
2743
2744
2744
2745
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" )
2745
2809
}
2746
2810
2747
2811
// testCustomChannelsLiquidityEdgeCases is a test that runs through some
@@ -2751,7 +2815,7 @@ func testCustomChannelsLiquidityEdgeCases(ctx context.Context,
2751
2815
2752
2816
// Run liquidity edge cases and only use single asset IDs for invoices
2753
2817
// and payments.
2754
- testCustomChannelsLiquidtyEdgeCasesCore (ctx , net , t , false )
2818
+ testCustomChannelsLiquidityEdgeCasesCore (ctx , net , t , false )
2755
2819
}
2756
2820
2757
2821
// testCustomChannelsLiquidityEdgeCasesGroup is a test that runs through some
@@ -2761,7 +2825,7 @@ func testCustomChannelsLiquidityEdgeCasesGroup(ctx context.Context,
2761
2825
2762
2826
// Run liquidity edge cases and only use group keys for invoices and
2763
2827
// payments.
2764
- testCustomChannelsLiquidtyEdgeCasesCore (ctx , net , t , true )
2828
+ testCustomChannelsLiquidityEdgeCasesCore (ctx , net , t , true )
2765
2829
}
2766
2830
2767
2831
// testCustomChannelsStrictForwarding is a test that tests the strict forwarding
0 commit comments