@@ -4770,3 +4770,146 @@ func testCustomChannelsSelfPayment(ctx context.Context, net *NetworkHarness,
47704770 )
47714771 }
47724772}
4773+
4774+ // testCustomChannelsMultiChannelPathfinding tests that multiple channels with
4775+ // different assets are properly considered when pathfinding for payments.
4776+ func testCustomChannelsMultiChannelPathfinding (ctx context.Context ,
4777+ net * NetworkHarness , t * harnessTest ) {
4778+
4779+ lndArgs := slices .Clone (lndArgsTemplate )
4780+ litdArgs := slices .Clone (litdArgsTemplate )
4781+
4782+ // We use Alice as the proof courier. But in order for Alice to also
4783+ // use itself, we need to define its port upfront.
4784+ alicePort := port .NextAvailablePort ()
4785+ litdArgs = append (litdArgs , fmt .Sprintf (
4786+ "--taproot-assets.proofcourieraddr=%s://%s" ,
4787+ proof .UniverseRpcCourierType ,
4788+ fmt .Sprintf (node .ListenerFormat , alicePort ),
4789+ ))
4790+
4791+ // Next, we'll make Alice and Bob, who will be the main nodes under
4792+ // test.
4793+ alice , err := net .NewNodeWithPort (
4794+ t .t , "Alice" , lndArgs , false , true , alicePort , litdArgs ... ,
4795+ )
4796+ require .NoError (t .t , err )
4797+ bob , err := net .NewNode (
4798+ t .t , "Bob" , lndArgs , false , true , litdArgs ... ,
4799+ )
4800+ require .NoError (t .t , err )
4801+
4802+ charlie , err := net .NewNode (
4803+ t .t , "Charlie" , lndArgs , false , true , litdArgs ... ,
4804+ )
4805+ require .NoError (t .t , err )
4806+
4807+ // Now we'll connect all nodes, and also fund them with some coins.
4808+ nodes := []* HarnessNode {alice , bob , charlie }
4809+ connectAllNodes (t .t , net , nodes )
4810+ fundAllNodes (t .t , net , nodes )
4811+
4812+ aliceTap := newTapClient (t .t , alice )
4813+
4814+ // Next, we'll mint an asset for Alice, who will be the node that opens
4815+ // the channel outbound.
4816+ mintedAssets1 := itest .MintAssetsConfirmBatch (
4817+ t .t , t .lndHarness .Miner .Client , aliceTap ,
4818+ []* mintrpc.MintAssetRequest {
4819+ {
4820+ Asset : itestAsset ,
4821+ },
4822+ },
4823+ )
4824+ cents := mintedAssets1 [0 ]
4825+ assetIDCents := cents .AssetGenesis .AssetId
4826+
4827+ // We'll mint a second asset, representing british pences.
4828+ mintedAssets2 := itest .MintAssetsConfirmBatch (
4829+ t .t , t .lndHarness .Miner .Client , aliceTap ,
4830+ []* mintrpc.MintAssetRequest {
4831+ {
4832+ Asset : & mintrpc.MintAsset {
4833+ AssetType : taprpc .AssetType_NORMAL ,
4834+ Name : "itest-asset-pences" ,
4835+ AssetMeta : dummyMetaData ,
4836+ Amount : 1_000_000 ,
4837+ },
4838+ },
4839+ },
4840+ )
4841+ pences := mintedAssets2 [0 ]
4842+ assetIDPences := pences .AssetGenesis .AssetId
4843+
4844+ t .Logf ("Minted %d lightning cents and %d lightning pences, syncing " +
4845+ "universes..." , cents .Amount , pences .Amount )
4846+ syncUniverses (t .t , aliceTap , bob )
4847+ t .Logf ("Universes synced between all nodes, distributing assets..." )
4848+
4849+ // With the assets created, and synced -- we'll now open the channel
4850+ // between Alice and Bob.
4851+ t .Logf ("Opening asset channel with cents..." )
4852+ assetFundResp1 , err := aliceTap .FundChannel (
4853+ ctx , & tchrpc.FundChannelRequest {
4854+ AssetAmount : fundingAmount ,
4855+ AssetId : assetIDCents ,
4856+ PeerPubkey : bob .PubKey [:],
4857+ FeeRateSatPerVbyte : 5 ,
4858+ },
4859+ )
4860+ require .NoError (t .t , err )
4861+ t .Logf ("Funded cents channel between Alice and Bob: %v" , assetFundResp1 )
4862+
4863+ // With the channel open, mine a block to confirm it.
4864+ mineBlocks (t , net , 6 , 1 )
4865+
4866+ t .Logf ("Opening asset channel with pences..." )
4867+ assetFundResp2 , err := aliceTap .FundChannel (
4868+ ctx , & tchrpc.FundChannelRequest {
4869+ AssetAmount : fundingAmount ,
4870+ AssetId : assetIDPences ,
4871+ PeerPubkey : bob .PubKey [:],
4872+ FeeRateSatPerVbyte : 5 ,
4873+ },
4874+ )
4875+ require .NoError (t .t , err )
4876+ t .Logf ("Funded pences channel between Alice and Bob: %v" ,
4877+ assetFundResp2 )
4878+
4879+ // With the channel open, mine a block to confirm it.
4880+ mineBlocks (t , net , 6 , 1 )
4881+
4882+ t .Logf ("Opening normal channel between Bob and Charlie..." )
4883+ satChanPoint := openChannelAndAssert (
4884+ t , net , bob , charlie , lntest.OpenChannelParams {
4885+ Amt : 10_000_000 ,
4886+ SatPerVByte : 5 ,
4887+ },
4888+ )
4889+ defer closeChannelAndAssert (t , net , charlie , satChanPoint , false )
4890+
4891+ // Before we start sending out payments, let's make sure each node can
4892+ // see the other one in the graph and has all required features.
4893+ require .NoError (t .t , t .lndHarness .AssertNodeKnown (alice , bob ))
4894+ require .NoError (t .t , t .lndHarness .AssertNodeKnown (bob , alice ))
4895+ require .NoError (t .t , t .lndHarness .AssertNodeKnown (alice , charlie ))
4896+
4897+ // We now make sure that the balance of the cents channel is higher on
4898+ // Alice, by sending some of the pences to Bob in a keysend payment.
4899+ const pencesKeySendAmount = 5_000
4900+ sendAssetKeySendPayment (
4901+ t .t , alice , bob , pencesKeySendAmount , assetIDPences ,
4902+ fn .None [int64 ](),
4903+ )
4904+
4905+ logBalance (t .t , nodes , assetIDCents , "cents, after keysend pences" )
4906+ logBalance (t .t , nodes , assetIDPences , "pences, after keysend pences" )
4907+
4908+ // We now create a normal invoice on Charlie for some amount, then try
4909+ // to pay it with pences.
4910+ const btcInvoiceAmount = 500_00
4911+ invoiceResp := createNormalInvoice (t .t , charlie , btcInvoiceAmount )
4912+ payInvoiceWithAssets (
4913+ t .t , alice , bob , invoiceResp .PaymentRequest , assetIDPences ,
4914+ )
4915+ }
0 commit comments