@@ -2147,3 +2147,123 @@ func testCustomChannelsBalanceConsistency(_ context.Context,
21472147 assertNumAssetOutputs (t .t , charlieTap , assetID , 1 )
21482148 assertNumAssetOutputs (t .t , daveTap , assetID , 1 )
21492149}
2150+
2151+ // testCustomChannelsSingleAssetMultiInput tests whether it is possible to fund
2152+ // a channel using FundChannel that uses multiple inputs from the same asset.
2153+ func testCustomChannelsSingleAssetMultiInput (_ context.Context ,
2154+ net * NetworkHarness , t * harnessTest ) {
2155+
2156+ ctxb := context .Background ()
2157+ lndArgs := slices .Clone (lndArgsTemplate )
2158+ litdArgs := slices .Clone (litdArgsTemplate )
2159+
2160+ zane , err := net .NewNode (
2161+ t .t , "Zane" , lndArgs , false , true , litdArgs ... ,
2162+ )
2163+ require .NoError (t .t , err )
2164+
2165+ litdArgs = append (litdArgs , fmt .Sprintf (
2166+ "--taproot-assets.proofcourieraddr=%s://%s" ,
2167+ proof .UniverseRpcCourierType , zane .Cfg .LitAddr (),
2168+ ))
2169+
2170+ charlie , err := net .NewNode (
2171+ t .t , "Charlie" , lndArgs , false , true , litdArgs ... ,
2172+ )
2173+ require .NoError (t .t , err )
2174+ dave , err := net .NewNode (t .t , "Dave" , lndArgs , false , true , litdArgs ... )
2175+ require .NoError (t .t , err )
2176+
2177+ nodes := []* HarnessNode {charlie , dave }
2178+ connectAllNodes (t .t , net , nodes )
2179+ fundAllNodes (t .t , net , nodes )
2180+
2181+ charlieTap := newTapClient (t .t , charlie )
2182+ daveTap := newTapClient (t .t , dave )
2183+
2184+ // Mint an assets on Charlie and sync Dave to Charlie as the universe.
2185+ mintedAssets := itest .MintAssetsConfirmBatch (
2186+ t .t , t .lndHarness .Miner .Client , charlieTap ,
2187+ []* mintrpc.MintAssetRequest {
2188+ {
2189+ Asset : itestAsset ,
2190+ },
2191+ },
2192+ )
2193+ cents := mintedAssets [0 ]
2194+ assetID := cents .AssetGenesis .AssetId
2195+
2196+ t .Logf ("Minted %d lightning cents, syncing universes..." ,
2197+ cents .Amount )
2198+ syncUniverses (t .t , charlieTap , dave )
2199+ t .Logf ("Universes synced between all nodes, distributing assets..." )
2200+
2201+ // Charlie should have two balance outputs with the full balance.
2202+ assertAssetBalance (t .t , charlieTap , assetID , cents .Amount )
2203+
2204+ // Send assets to Dave so he can fund a channel.
2205+ halfCentsAmount := cents .Amount / 2
2206+ daveAddr1 , err := daveTap .NewAddr (ctxb , & taprpc.NewAddrRequest {
2207+ Amt : halfCentsAmount ,
2208+ AssetId : assetID ,
2209+ ProofCourierAddr : fmt .Sprintf (
2210+ "%s://%s" , proof .UniverseRpcCourierType ,
2211+ charlieTap .node .Cfg .LitAddr (),
2212+ ),
2213+ })
2214+ require .NoError (t .t , err )
2215+ daveAddr2 , err := daveTap .NewAddr (ctxb , & taprpc.NewAddrRequest {
2216+ Amt : halfCentsAmount ,
2217+ AssetId : assetID ,
2218+ ProofCourierAddr : fmt .Sprintf (
2219+ "%s://%s" , proof .UniverseRpcCourierType ,
2220+ charlieTap .node .Cfg .LitAddr (),
2221+ ),
2222+ })
2223+ require .NoError (t .t , err )
2224+
2225+ t .Logf ("Sending %v asset units to Dave twice..." , halfCentsAmount )
2226+
2227+ // Send the assets to Dave.
2228+ itest .AssertAddrCreated (t .t , daveTap , cents , daveAddr1 )
2229+ itest .AssertAddrCreated (t .t , daveTap , cents , daveAddr2 )
2230+ sendResp , err := charlieTap .SendAsset (ctxb , & taprpc.SendAssetRequest {
2231+ TapAddrs : []string {daveAddr1 .Encoded , daveAddr2 .Encoded },
2232+ })
2233+ require .NoError (t .t , err )
2234+ itest .ConfirmAndAssertOutboundTransferWithOutputs (
2235+ t .t , t .lndHarness .Miner .Client , charlieTap , sendResp , assetID ,
2236+ []uint64 {
2237+ cents .Amount - 2 * halfCentsAmount , halfCentsAmount ,
2238+ halfCentsAmount ,
2239+ }, 0 , 1 , 3 ,
2240+ )
2241+ itest .AssertNonInteractiveRecvComplete (t .t , daveTap , 2 )
2242+
2243+ // Fund a channel using multiple inputs from the same asset.
2244+ fundRespCD , err := daveTap .FundChannel (
2245+ ctxb , & tchrpc.FundChannelRequest {
2246+ AssetAmount : 2 * halfCentsAmount ,
2247+ AssetId : assetID ,
2248+ PeerPubkey : charlieTap .node .PubKey [:],
2249+ FeeRateSatPerVbyte : 5 ,
2250+ PushSat : 0 ,
2251+ },
2252+ )
2253+ require .NoError (t .t , err )
2254+ t .Logf ("Funded channel between Charlie and Dave: %v" , fundRespCD )
2255+
2256+ // Let's confirm the channel.
2257+ mineBlocks (t , net , 6 , 1 )
2258+
2259+ // Tapd should not report any balance for Charlie, since the asset is
2260+ // used in a funding transaction. It should also not report any balance
2261+ // for Dave. All those balances are reported through channel balances.
2262+ assertAssetBalance (t .t , charlieTap , assetID , 0 )
2263+ assertAssetBalance (t .t , daveTap , assetID , 0 )
2264+
2265+ // Make sure the channel shows the correct asset information.
2266+ assertAssetChan (
2267+ t .t , charlieTap .node , daveTap .node , 2 * halfCentsAmount , assetID ,
2268+ )
2269+ }
0 commit comments