@@ -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"
@@ -2220,12 +2221,12 @@ func testCustomChannelsBreach(ctx context.Context, net *NetworkHarness,
2220
2221
t .Logf ("Charlie UTXOs after breach: %v" , toProtoJSON (t .t , charlieUTXOs ))
2221
2222
}
2222
2223
2223
- // testCustomChannelsLiquidtyEdgeCasesCore is the core logic of the liquidity
2224
+ // testCustomChannelsLiquidityEdgeCasesCore is the core logic of the liquidity
2224
2225
// edge cases. This test goes through certain scenarios that expose edge cases
2225
2226
// and behaviors that proved to be buggy in the past and have been directly
2226
2227
// addressed. It accepts an extra parameter which dictates whether it should use
2227
2228
// group keys or asset IDs.
2228
- func testCustomChannelsLiquidtyEdgeCasesCore (ctx context.Context ,
2229
+ func testCustomChannelsLiquidityEdgeCasesCore (ctx context.Context ,
2229
2230
net * NetworkHarness , t * harnessTest , groupMode bool ) {
2230
2231
2231
2232
lndArgs := slices .Clone (lndArgsTemplate )
@@ -2723,6 +2724,69 @@ func testCustomChannelsLiquidtyEdgeCasesCore(ctx context.Context,
2723
2724
)
2724
2725
2725
2726
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" )
2726
2790
}
2727
2791
2728
2792
// testCustomChannelsLiquidityEdgeCases is a test that runs through some
@@ -2732,7 +2796,7 @@ func testCustomChannelsLiquidityEdgeCases(ctx context.Context,
2732
2796
2733
2797
// Run liquidity edge cases and only use single asset IDs for invoices
2734
2798
// and payments.
2735
- testCustomChannelsLiquidtyEdgeCasesCore (ctx , net , t , false )
2799
+ testCustomChannelsLiquidityEdgeCasesCore (ctx , net , t , false )
2736
2800
}
2737
2801
2738
2802
// testCustomChannelsLiquidityEdgeCasesGroup is a test that runs through some
@@ -2742,7 +2806,7 @@ func testCustomChannelsLiquidityEdgeCasesGroup(ctx context.Context,
2742
2806
2743
2807
// Run liquidity edge cases and only use group keys for invoices and
2744
2808
// payments.
2745
- testCustomChannelsLiquidtyEdgeCasesCore (ctx , net , t , true )
2809
+ testCustomChannelsLiquidityEdgeCasesCore (ctx , net , t , true )
2746
2810
}
2747
2811
2748
2812
// testCustomChannelsStrictForwarding is a test that tests the strict forwarding
0 commit comments