@@ -2773,9 +2773,20 @@ func testCustomChannelsFee(_ context.Context,
27732773// testCustomChannelsHtlcForceClose tests that we can force close a channel
27742774// with HTLCs in both directions and that the HTLC outputs are correctly
27752775// swept.
2776- func testCustomChannelsHtlcForceClose (_ context.Context , net * NetworkHarness ,
2776+ func testCustomChannelsHtlcForceClose (ctxb context.Context , net * NetworkHarness ,
27772777 t * harnessTest ) {
27782778
2779+ runCustomChannelsHtlcForceClose (ctxb , t , net , false )
2780+ runCustomChannelsHtlcForceClose (ctxb , t , net , true )
2781+ }
2782+
2783+ // runCustomChannelsHtlcForceClose is a helper function that runs the HTLC force
2784+ // close test with the given MPP setting.
2785+ func runCustomChannelsHtlcForceClose (ctxb context.Context , t * harnessTest ,
2786+ net * NetworkHarness , mpp bool ) {
2787+
2788+ t .Logf ("Running test with MPP: %v" , mpp )
2789+
27792790 lndArgs := slices .Clone (lndArgsTemplate )
27802791 litdArgs := slices .Clone (litdArgsTemplate )
27812792
@@ -2829,7 +2840,6 @@ func testCustomChannelsHtlcForceClose(_ context.Context, net *NetworkHarness,
28292840 // With the assets created, and synced -- we'll now open the channel
28302841 // between Alice and Bob.
28312842 t .Logf ("Opening asset channels..." )
2832- ctxb := context .Background ()
28332843 assetFundResp , err := aliceTap .FundChannel (
28342844 ctxb , & tchrpc.FundChannelRequest {
28352845 AssetAmount : fundingAmount ,
@@ -2853,7 +2863,7 @@ func testCustomChannelsHtlcForceClose(_ context.Context, net *NetworkHarness,
28532863 // to be able to extend HTLCs in the other direction.
28542864 const (
28552865 numPayments = 10
2856- keySendAmount = 1_000
2866+ keySendAmount = 2_500
28572867 )
28582868 for i := 0 ; i < numPayments ; i ++ {
28592869 sendAssetKeySendPayment (
@@ -2866,11 +2876,19 @@ func testCustomChannelsHtlcForceClose(_ context.Context, net *NetworkHarness,
28662876 // Now that both parties have some funds, we'll move onto the main test.
28672877 //
28682878 // We'll make 2 hodl invoice for each peer, so 4 total. From Alice's
2869- // PoV, she'll have two outgoing HTLCs, and two incoming HTLCs.
2879+ // PoV, she'll have two outgoing HTLCs (or +4 with MPP), and two
2880+ // incoming HTLCs.
28702881 var (
28712882 bobHodlInvoices []assetHodlInvoice
28722883 aliceHodlInvoices []assetHodlInvoice
2873- assetInvoiceAmt = 100
2884+
2885+ // The default oracle rate is 17_180 mSat/asset unit, so 10_000
2886+ // will be equal to 171_800_000 mSat. When we use the mpp bool
2887+ // for the smallShards param of payInvoiceWithAssets, that
2888+ // means we'll split the payment into shards of 80_000_000 mSat
2889+ // max. So we'll get three shards per payment.
2890+ assetInvoiceAmt = 10_000
2891+ assetsPerMPPShard = 4656
28742892 )
28752893 for i := 0 ; i < 2 ; i ++ {
28762894 bobHodlInvoices = append (
@@ -2892,7 +2910,7 @@ func testCustomChannelsHtlcForceClose(_ context.Context, net *NetworkHarness,
28922910 // yet.
28932911 for _ , aliceInvoice := range aliceHodlInvoices {
28942912 payInvoiceWithAssets (
2895- t .t , bob , alice , aliceInvoice .payReq , assetID , false ,
2913+ t .t , bob , alice , aliceInvoice .payReq , assetID , mpp ,
28962914 fn .Some (lnrpc .Payment_IN_FLIGHT ),
28972915 )
28982916 }
@@ -2903,9 +2921,15 @@ func testCustomChannelsHtlcForceClose(_ context.Context, net *NetworkHarness,
29032921 )
29042922 }
29052923
2906- // At this point, both sides should have 4 HTLCs active.
2907- assertNumHtlcs (t .t , alice , 4 )
2908- assertNumHtlcs (t .t , bob , 4 )
2924+ // At this point, both sides should have 4 (or +4 with MPP) HTLCs
2925+ // active.
2926+ numHtlcs := 4
2927+ if mpp {
2928+ numAdditionalShards := assetInvoiceAmt / assetsPerMPPShard
2929+ numHtlcs += numAdditionalShards * 2
2930+ }
2931+ assertNumHtlcs (t .t , alice , numHtlcs )
2932+ assertNumHtlcs (t .t , bob , numHtlcs )
29092933
29102934 // Before we force close, we'll grab the current height, the CSV delay
29112935 // needed, and also the absolute timeout of the set of active HTLCs.
@@ -2947,8 +2971,8 @@ func testCustomChannelsHtlcForceClose(_ context.Context, net *NetworkHarness,
29472971 // At this point, the commitment transaction has been mined, and we have
29482972 // 4 total HTLCs on Alice's commitment transaction:
29492973 //
2950- // * 2x outgoing HTLCs to Alice to Bob
2951- // * 2x incoming HTLCs from Bob to Alice
2974+ // * 2x outgoing HTLCs from Alice to Bob
2975+ // * 2x incoming HTLCs from Bob to Alice (+2 with MPP)
29522976 //
29532977 // We'll leave half the HTLCs timeout, while pulling the other half.
29542978 // To start, we'll signal Bob to settle one of his incoming HTLCs on
@@ -2971,7 +2995,7 @@ func testCustomChannelsHtlcForceClose(_ context.Context, net *NetworkHarness,
29712995 // We'll mine an empty block to get the sweeper to tick.
29722996 mineBlocks (t , net , 1 , 0 )
29732997
2974- sweepTx1 , err := waitForNTxsInMempool (
2998+ bobSweepTx1 , err := waitForNTxsInMempool (
29752999 net .Miner .Client , 1 , shortTimeout ,
29763000 )
29773001 require .NoError (t .t , err )
@@ -2984,15 +3008,17 @@ func testCustomChannelsHtlcForceClose(_ context.Context, net *NetworkHarness,
29843008 // At this point, we should have the next sweep transaction in the
29853009 // mempool: Bob's incoming HTLC sweep directly off the commitment
29863010 // transaction.
2987- sweepTx2 , err := waitForNTxsInMempool (net .Miner .Client , 1 , shortTimeout )
3011+ bobSweepTx2 , err := waitForNTxsInMempool (
3012+ net .Miner .Client , 1 , shortTimeout ,
3013+ )
29883014 require .NoError (t .t , err )
29893015
29903016 // We'll now mine the next block, which should confirm Bob's HTLC sweep
29913017 // transaction.
29923018 mineBlocks (t , net , 1 , 1 )
29933019
2994- bobSweepTransfer1 := locateAssetTransfers (t .t , bobTap , * sweepTx1 [0 ])
2995- bobSweepTransfer2 := locateAssetTransfers (t .t , bobTap , * sweepTx2 [0 ])
3020+ bobSweepTransfer1 := locateAssetTransfers (t .t , bobTap , * bobSweepTx1 [0 ])
3021+ bobSweepTransfer2 := locateAssetTransfers (t .t , bobTap , * bobSweepTx2 [0 ])
29963022 t .Logf ("Bob's sweep transfer 1: %v" ,
29973023 toProtoJSON (t .t , bobSweepTransfer1 ))
29983024 t .Logf ("Bob's sweep transfer 2: %v" ,
@@ -3006,9 +3032,8 @@ func testCustomChannelsHtlcForceClose(_ context.Context, net *NetworkHarness,
30063032 // RFQ conversion.
30073033 bobExpectedBalance := closeExpiryInfo .remoteAssetBalance +
30083034 uint64 (assetInvoiceAmt - 1 )
3009- assertSpendableBalance (
3010- t .t , bobTap , assetID , bobExpectedBalance ,
3011- )
3035+ t .Logf ("Expecting Bob's balance to be %d" , bobExpectedBalance )
3036+ assertSpendableBalance (t .t , bobTap , assetID , bobExpectedBalance )
30123037
30133038 // With Bob's HTLC settled, we'll now have Alice do the same. For her,
30143039 // it'll be a 2nd level sweep, which requires an extra transaction.
@@ -3018,15 +3043,26 @@ func testCustomChannelsHtlcForceClose(_ context.Context, net *NetworkHarness,
30183043 // that she's swept everything properly. With the way the sweeper works,
30193044 // we need to mine one extra block before the sweeper picks things up.
30203045 mineBlocks (t , net , 1 , 0 )
3021- time .Sleep (time .Second * 1 )
3046+
3047+ aliceSweepTx1 , err := waitForNTxsInMempool (
3048+ net .Miner .Client , 1 , shortTimeout ,
3049+ )
3050+ require .NoError (t .t , err )
3051+
30223052 mineBlocks (t , net , 1 , 1 )
30233053
3054+ aliceSweepTransfer1 := locateAssetTransfers (
3055+ t .t , aliceTap , * aliceSweepTx1 [0 ],
3056+ )
3057+ t .Logf ("Alice's sweep transfer 1: %v" ,
3058+ toProtoJSON (t .t , aliceSweepTransfer1 ))
3059+
30243060 t .Logf ("Confirming Alice's to-local sweep" )
30253061
30263062 // With this extra block mined, Alice's settled balance should be the
30273063 // starting balance, minus the 2 HTLCs, plus her settled balance.
30283064 aliceExpectedBalance := itestAsset .Amount - fundingAmount
3029- aliceExpectedBalance += uint64 ( closeExpiryInfo .localAssetBalance )
3065+ aliceExpectedBalance += closeExpiryInfo .localAssetBalance
30303066 assertSpendableBalance (
30313067 t .t , aliceTap , assetID , aliceExpectedBalance ,
30323068 )
@@ -3056,9 +3092,27 @@ func testCustomChannelsHtlcForceClose(_ context.Context, net *NetworkHarness,
30563092 // If the block mined above didn't also mine our sweep, then we'll mine
30573093 // one final block which will confirm Alice's sweep transaction.
30583094 if len (sweepBlocks [0 ].Transactions ) == 1 {
3095+ sweepTx , err := waitForNTxsInMempool (
3096+ net .Miner .Client , 1 , shortTimeout ,
3097+ )
3098+ require .NoError (t .t , err )
3099+
30593100 // With the sweep transaction in the mempool, we'll mine a block
30603101 // to confirm the sweep.
30613102 mineBlocks (t , net , 1 , 1 )
3103+
3104+ aliceSweepTransfer := locateAssetTransfers (
3105+ t .t , aliceTap , * sweepTx [0 ],
3106+ )
3107+ t .Logf ("Alice's first-level sweep transfer: %v" ,
3108+ toProtoJSON (t .t , aliceSweepTransfer ))
3109+ } else {
3110+ sweepTx := sweepBlocks [0 ].Transactions [1 ]
3111+ aliceSweepTransfer := locateAssetTransfers (
3112+ t .t , aliceTap , sweepTx .TxHash (),
3113+ )
3114+ t .Logf ("Alice's first-level sweep transfer: %v" ,
3115+ toProtoJSON (t .t , aliceSweepTransfer ))
30623116 }
30633117
30643118 t .Logf ("Confirming Alice's second level remote HTLC success sweep" )
@@ -3085,7 +3139,25 @@ func testCustomChannelsHtlcForceClose(_ context.Context, net *NetworkHarness,
30853139 // If the block mined above didn't also mine our sweep, then we'll mine
30863140 // one final block which will confirm Alice's sweep transaction.
30873141 if len (sweepBlocks [0 ].Transactions ) == 1 {
3142+ sweepTx , err := waitForNTxsInMempool (
3143+ net .Miner .Client , 1 , shortTimeout ,
3144+ )
3145+ require .NoError (t .t , err )
3146+
30883147 mineBlocks (t , net , 1 , 1 )
3148+
3149+ aliceSweepTransfer := locateAssetTransfers (
3150+ t .t , aliceTap , * sweepTx [0 ],
3151+ )
3152+ t .Logf ("Alice's second-level sweep transfer: %v" ,
3153+ toProtoJSON (t .t , aliceSweepTransfer ))
3154+ } else {
3155+ sweepTx := sweepBlocks [0 ].Transactions [1 ]
3156+ aliceSweepTransfer := locateAssetTransfers (
3157+ t .t , aliceTap , sweepTx .TxHash (),
3158+ )
3159+ t .Logf ("Alice's second-level sweep transfer: %v" ,
3160+ toProtoJSON (t .t , aliceSweepTransfer ))
30893161 }
30903162
30913163 // With the sweep transaction confirmed, Alice's balance should have
@@ -3153,14 +3225,33 @@ func testCustomChannelsHtlcForceClose(_ context.Context, net *NetworkHarness,
31533225 // If the block mined above didn't also mine our sweep, then we'll mine
31543226 // one final block which will confirm Alice's sweep transaction.
31553227 if len (sweepBlocks [0 ].Transactions ) == 1 {
3228+ sweepTx , err := waitForNTxsInMempool (
3229+ net .Miner .Client , 1 , shortTimeout ,
3230+ )
3231+ require .NoError (t .t , err )
3232+
31563233 // We'll mine one final block which will confirm Alice's sweep
31573234 // transaction.
31583235 mineBlocks (t , net , 1 , 1 )
3236+
3237+ aliceSweepTransfer := locateAssetTransfers (
3238+ t .t , aliceTap , * sweepTx [0 ],
3239+ )
3240+ t .Logf ("Alice's final timeout sweep transfer: %v" ,
3241+ toProtoJSON (t .t , aliceSweepTransfer ))
3242+ } else {
3243+ sweepTx := sweepBlocks [0 ].Transactions [1 ]
3244+ aliceSweepTransfer := locateAssetTransfers (
3245+ t .t , aliceTap , sweepTx .TxHash (),
3246+ )
3247+ t .Logf ("Alice's final timeout sweep transfer: %v" ,
3248+ toProtoJSON (t .t , aliceSweepTransfer ))
31593249 }
31603250
31613251 // Finally, we'll assert that Alice's balance has been incremented by
31623252 // the timeout value.
31633253 aliceExpectedBalance += uint64 (assetInvoiceAmt - 1 )
3254+ t .Logf ("Expecting Alice's balance to be %d" , aliceExpectedBalance )
31643255 assertSpendableBalance (
31653256 t .t , aliceTap , assetID , aliceExpectedBalance ,
31663257 )
0 commit comments