@@ -6,15 +6,16 @@ import (
66 "slices"
77 "time"
88
9+ "github.com/btcsuite/btcd/btcec/v2/schnorr"
910 "github.com/btcsuite/btcd/btcutil"
1011 "github.com/btcsuite/btcd/chaincfg/chainhash"
1112 "github.com/lightninglabs/taproot-assets/itest"
1213 "github.com/lightninglabs/taproot-assets/proof"
13- "github.com/lightninglabs/taproot-assets/tapchannel"
1414 "github.com/lightninglabs/taproot-assets/taprpc"
1515 "github.com/lightninglabs/taproot-assets/taprpc/mintrpc"
1616 tchrpc "github.com/lightninglabs/taproot-assets/taprpc/tapchannelrpc"
1717 "github.com/lightninglabs/taproot-assets/taprpc/universerpc"
18+ "github.com/lightninglabs/taproot-assets/tapscript"
1819 "github.com/lightningnetwork/lnd/fn"
1920 "github.com/lightningnetwork/lnd/lnrpc"
2021 "github.com/lightningnetwork/lnd/lntest"
@@ -353,7 +354,7 @@ func testCustomChannels(_ context.Context, net *NetworkHarness,
353354 )
354355 cents := mintedAssets [0 ]
355356 assetID := cents .AssetGenesis .AssetId
356- fundingScriptTree := tapchannel .NewFundingScriptTree ()
357+ fundingScriptTree := tapscript .NewFundingScriptTree ()
357358 fundingScriptKey := fundingScriptTree .TaprootKey
358359 fundingScriptTreeBytes := fundingScriptKey .SerializeCompressed ()
359360
@@ -812,7 +813,7 @@ func testCustomChannelsGroupedAsset(_ context.Context, net *NetworkHarness,
812813 cents := mintedAssets [0 ]
813814 assetID := cents .AssetGenesis .AssetId
814815 groupID := cents .GetAssetGroup ().GetTweakedGroupKey ()
815- fundingScriptTree := tapchannel .NewFundingScriptTree ()
816+ fundingScriptTree := tapscript .NewFundingScriptTree ()
816817 fundingScriptKey := fundingScriptTree .TaprootKey
817818 fundingScriptTreeBytes := fundingScriptKey .SerializeCompressed ()
818819
@@ -1230,7 +1231,7 @@ func testCustomChannelsForceClose(_ context.Context, net *NetworkHarness,
12301231
12311232 // Make sure that Charlie properly uploaded funding proof to the
12321233 // Universe server.
1233- fundingScriptTree := tapchannel .NewFundingScriptTree ()
1234+ fundingScriptTree := tapscript .NewFundingScriptTree ()
12341235 fundingScriptKey := fundingScriptTree .TaprootKey
12351236 fundingScriptTreeBytes := fundingScriptKey .SerializeCompressed ()
12361237 assertUniverseProofExists (
@@ -1568,7 +1569,7 @@ func testCustomChannelsBreach(_ context.Context, net *NetworkHarness,
15681569
15691570 // Make sure that Charlie properly uploaded funding proof to the
15701571 // Universe server.
1571- fundingScriptTree := tapchannel .NewFundingScriptTree ()
1572+ fundingScriptTree := tapscript .NewFundingScriptTree ()
15721573 fundingScriptKey := fundingScriptTree .TaprootKey
15731574 fundingScriptTreeBytes := fundingScriptKey .SerializeCompressed ()
15741575 assertUniverseProofExists (
@@ -1748,7 +1749,7 @@ func testCustomChannelsLiquidityEdgeCases(_ context.Context,
17481749 if cents .AssetGroup != nil {
17491750 groupKey = cents .AssetGroup .TweakedGroupKey
17501751 }
1751- fundingScriptTree := tapchannel .NewFundingScriptTree ()
1752+ fundingScriptTree := tapscript .NewFundingScriptTree ()
17521753 fundingScriptKey := fundingScriptTree .TaprootKey
17531754 fundingScriptTreeBytes := fundingScriptKey .SerializeCompressed ()
17541755
@@ -1894,3 +1895,202 @@ func testCustomChannelsLiquidityEdgeCases(_ context.Context,
18941895
18951896 logBalance (t .t , nodes , assetID , "after giant asset payment" )
18961897}
1898+
1899+ // testCustomChannelsBalanceConsistency is a test that test the balance .
1900+ func testCustomChannelsBalanceConsistency (_ context.Context ,
1901+ net * NetworkHarness , t * harnessTest ) {
1902+
1903+ ctxb := context .Background ()
1904+ lndArgs := slices .Clone (lndArgsTemplate )
1905+ litdArgs := slices .Clone (litdArgsTemplate )
1906+
1907+ zane , err := net .NewNode (
1908+ t .t , "Zane" , lndArgs , false , true , litdArgs ... ,
1909+ )
1910+ require .NoError (t .t , err )
1911+
1912+ litdArgs = append (litdArgs , fmt .Sprintf (
1913+ "--taproot-assets.proofcourieraddr=%s://%s" ,
1914+ proof .UniverseRpcCourierType , zane .Cfg .LitAddr (),
1915+ ))
1916+
1917+ charlie , err := net .NewNode (
1918+ t .t , "Charlie" , lndArgs , false , true , litdArgs ... ,
1919+ )
1920+ require .NoError (t .t , err )
1921+ dave , err := net .NewNode (t .t , "Dave" , lndArgs , false , true , litdArgs ... )
1922+ require .NoError (t .t , err )
1923+
1924+ nodes := []* HarnessNode {charlie , dave }
1925+ connectAllNodes (t .t , net , nodes )
1926+ fundAllNodes (t .t , net , nodes )
1927+
1928+ charlieTap := newTapClient (t .t , charlie )
1929+ daveTap := newTapClient (t .t , dave )
1930+ universeTap := newTapClient (t .t , zane )
1931+
1932+ // Mint an asset on Charlie and sync Dave to Charlie as the universe.
1933+ mintedAssets := itest .MintAssetsConfirmBatch (
1934+ t .t , t .lndHarness .Miner .Client , charlieTap ,
1935+ []* mintrpc.MintAssetRequest {
1936+ {
1937+ Asset : itestAsset ,
1938+ },
1939+ },
1940+ )
1941+ cents := mintedAssets [0 ]
1942+ assetID := cents .AssetGenesis .AssetId
1943+ var groupKey []byte
1944+ if cents .AssetGroup != nil {
1945+ groupKey = cents .AssetGroup .TweakedGroupKey
1946+ }
1947+
1948+ t .Logf ("Minted %d lightning cents, syncing universes..." , cents .Amount )
1949+ syncUniverses (t .t , charlieTap , dave )
1950+ t .Logf ("Universes synced between all nodes, distributing assets..." )
1951+
1952+ charlieBalance := cents .Amount
1953+
1954+ // Charlie should have a single balance output with the full balance.
1955+ assertAssetBalance (t .t , charlieTap , assetID , cents .Amount )
1956+
1957+ // The script key should be local to charlie, and the script key should
1958+ // be known. It is after all the asset he just minted himself.
1959+ scriptKeyLocal := true
1960+ scriptKeyKnown := false
1961+ scriptKeyHasScriptPath := false
1962+
1963+ scriptKey , err := schnorr .ParsePubKey (cents .ScriptKey [1 :])
1964+ require .NoError (t .t , err )
1965+ assertAssetExists (
1966+ t .t , charlieTap , assetID , charlieBalance ,
1967+ scriptKey , scriptKeyLocal , scriptKeyKnown ,
1968+ scriptKeyHasScriptPath ,
1969+ )
1970+
1971+ fundingScriptTree := tapscript .NewFundingScriptTree ()
1972+ fundingScriptKey := fundingScriptTree .TaprootKey
1973+ fundingScriptTreeBytes := fundingScriptKey .SerializeCompressed ()
1974+
1975+ fundRespCD , err := charlieTap .FundChannel (
1976+ ctxb , & tchrpc.FundChannelRequest {
1977+ AssetAmount : charlieBalance ,
1978+ AssetId : assetID ,
1979+ PeerPubkey : daveTap .node .PubKey [:],
1980+ FeeRateSatPerVbyte : 5 ,
1981+ PushSat : 0 ,
1982+ },
1983+ )
1984+ require .NoError (t .t , err )
1985+ t .Logf ("Funded channel between Charlie and Dave: %v" , fundRespCD )
1986+
1987+ // Make sure the pending channel shows up in the list and has the
1988+ // custom records set as JSON.
1989+ assertPendingChannels (
1990+ t .t , charlieTap .node , assetID , 1 , charlieBalance , 0 ,
1991+ )
1992+
1993+ // Let's confirm the channel.
1994+ mineBlocks (t , net , 6 , 1 )
1995+
1996+ // Tapd should not report any balance for Charlie, since the asset is
1997+ // used in a funding transaction. It should also not report any balance
1998+ // for Dave. All those balances are reported through channel balances.
1999+ assertAssetBalance (t .t , charlieTap , assetID , 0 )
2000+ assertAssetBalance (t .t , daveTap , assetID , 0 )
2001+
2002+ // There should only be a single asset piece for Charlie, the one in the
2003+ // channel.
2004+ assertNumAssetOutputs (t .t , charlieTap , assetID , 1 )
2005+
2006+ // The script key should now not be local anymore, since he funded a
2007+ // channel with it. Charlie does still know the script key though.
2008+ scriptKeyLocal = false
2009+ scriptKeyKnown = true
2010+ scriptKeyHasScriptPath = true
2011+ assertAssetExists (
2012+ t .t , charlieTap , assetID , charlieBalance ,
2013+ fundingScriptKey , scriptKeyLocal , scriptKeyKnown ,
2014+ scriptKeyHasScriptPath ,
2015+ )
2016+
2017+ // Assert that the proofs for both channels has been uploaded to the
2018+ // designated Universe server.
2019+ assertUniverseProofExists (
2020+ t .t , universeTap , assetID , groupKey , fundingScriptTreeBytes ,
2021+ fmt .Sprintf ("%v:%v" , fundRespCD .Txid , fundRespCD .OutputIndex ),
2022+ )
2023+
2024+ // Make sure the channel shows the correct asset information.
2025+ assertAssetChan (
2026+ t .t , charlieTap .node , daveTap .node , charlieBalance , assetID ,
2027+ )
2028+
2029+ logBalance (t .t , nodes , assetID , "initial" )
2030+
2031+ // Normal case.
2032+ // Send 500 assets from Charlie to Dave.
2033+ sendAssetKeySendPayment (
2034+ t .t , charlie , dave , 500 , assetID ,
2035+ fn .None [int64 ](), lnrpc .Payment_SUCCEEDED ,
2036+ fn .None [lnrpc.PaymentFailureReason ](),
2037+ )
2038+
2039+ logBalance (t .t , nodes , assetID , "after 500 assets" )
2040+
2041+ // Tapd stould still not report balances for Charlie and Dave, since
2042+ // they are still locked up in the funding transaction.
2043+ assertAssetBalance (t .t , charlieTap , assetID , 0 )
2044+ assertAssetBalance (t .t , daveTap , assetID , 0 )
2045+
2046+ // Send 10k sats from Charlie to Dave. Dave needs the sats to be able to
2047+ // send assets.
2048+ sendKeySendPayment (t .t , charlie , dave , 10000 )
2049+
2050+ // Now Dave tries to send 250 assets.
2051+ sendAssetKeySendPayment (
2052+ t .t , dave , charlie , 250 , assetID ,
2053+ fn .None [int64 ](), lnrpc .Payment_SUCCEEDED ,
2054+ fn .None [lnrpc.PaymentFailureReason ](),
2055+ )
2056+
2057+ logBalance (t .t , nodes , assetID , "after 250 sats backwards" )
2058+
2059+ // Tapd stould still not report balances for Charlie and Dave, since
2060+ // they are still locked up in the funding transaction.
2061+ assertAssetBalance (t .t , charlieTap , assetID , 0 )
2062+ assertAssetBalance (t .t , daveTap , assetID , 0 )
2063+
2064+ // We will now close the channel.
2065+ t .Logf ("Close the channel between Charlie and Dave..." )
2066+ charlieChanPoint := & lnrpc.ChannelPoint {
2067+ OutputIndex : uint32 (fundRespCD .OutputIndex ),
2068+ FundingTxid : & lnrpc.ChannelPoint_FundingTxidStr {
2069+ FundingTxidStr : fundRespCD .Txid ,
2070+ },
2071+ }
2072+
2073+ closeChannelAndAssert (t , net , charlie , charlieChanPoint , false )
2074+
2075+ // Charlie should have a single balance output with the balance 250 less
2076+ // than the total amount minted.
2077+ assertAssetBalance (t .t , charlieTap , assetID , charlieBalance - 250 )
2078+ assertAssetBalance (t .t , daveTap , assetID , 250 )
2079+
2080+ // The script key should now be local to both Charlie and Dave, since
2081+ // the channel was closed.
2082+ scriptKeyLocal = true
2083+ scriptKeyKnown = true
2084+ scriptKeyHasScriptPath = false
2085+ assertAssetExists (
2086+ t .t , charlieTap , assetID , charlieBalance - 250 ,
2087+ nil , scriptKeyLocal , scriptKeyKnown , scriptKeyHasScriptPath ,
2088+ )
2089+ assertAssetExists (
2090+ t .t , daveTap , assetID , 250 ,
2091+ nil , scriptKeyLocal , scriptKeyKnown , scriptKeyHasScriptPath ,
2092+ )
2093+
2094+ assertNumAssetOutputs (t .t , charlieTap , assetID , 1 )
2095+ assertNumAssetOutputs (t .t , daveTap , assetID , 1 )
2096+ }
0 commit comments