@@ -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
@@ -1224,13 +1225,15 @@ func testCustomChannelsForceClose(_ context.Context, net *NetworkHarness,
12241225 t .Logf ("Channel funding transfer: %v" ,
12251226 toProtoJSON (t .t , assetFundingTransfer ))
12261227
1227- // Charlie's balance should reflect that the funding asset was added to
1228- // the DB.
1229- assertAssetBalance (t .t , charlieTap , assetID , itestAsset .Amount )
1228+ // Charlie's balance should reflect that the funding asset is now
1229+ // excluded from balance reporting by tapd.
1230+ assertAssetBalance (
1231+ t .t , charlieTap , assetID , itestAsset .Amount - fundingAmount ,
1232+ )
12301233
12311234 // Make sure that Charlie properly uploaded funding proof to the
12321235 // Universe server.
1233- fundingScriptTree := tapchannel .NewFundingScriptTree ()
1236+ fundingScriptTree := tapscript .NewFundingScriptTree ()
12341237 fundingScriptKey := fundingScriptTree .TaprootKey
12351238 fundingScriptTreeBytes := fundingScriptKey .SerializeCompressed ()
12361239 assertUniverseProofExists (
@@ -1562,13 +1565,15 @@ func testCustomChannelsBreach(_ context.Context, net *NetworkHarness,
15621565 t .Logf ("Channel funding transfer: %v" ,
15631566 toProtoJSON (t .t , assetFundingTransfer ))
15641567
1565- // Charlie's balance should reflect that the funding asset was added to
1566- // the DB.
1567- assertAssetBalance (t .t , charlieTap , assetID , itestAsset .Amount )
1568+ // Charlie's balance should reflect that the funding asset is now
1569+ // excluded from balance reporting by tapd.
1570+ assertAssetBalance (
1571+ t .t , charlieTap , assetID , itestAsset .Amount - fundingAmount ,
1572+ )
15681573
15691574 // Make sure that Charlie properly uploaded funding proof to the
15701575 // Universe server.
1571- fundingScriptTree := tapchannel .NewFundingScriptTree ()
1576+ fundingScriptTree := tapscript .NewFundingScriptTree ()
15721577 fundingScriptKey := fundingScriptTree .TaprootKey
15731578 fundingScriptTreeBytes := fundingScriptKey .SerializeCompressed ()
15741579 assertUniverseProofExists (
@@ -1748,7 +1753,7 @@ func testCustomChannelsLiquidityEdgeCases(_ context.Context,
17481753 if cents .AssetGroup != nil {
17491754 groupKey = cents .AssetGroup .TweakedGroupKey
17501755 }
1751- fundingScriptTree := tapchannel .NewFundingScriptTree ()
1756+ fundingScriptTree := tapscript .NewFundingScriptTree ()
17521757 fundingScriptKey := fundingScriptTree .TaprootKey
17531758 fundingScriptTreeBytes := fundingScriptKey .SerializeCompressed ()
17541759
@@ -1779,7 +1784,10 @@ func testCustomChannelsLiquidityEdgeCases(_ context.Context,
17791784 // Let's confirm the channel.
17801785 mineBlocks (t , net , 6 , 1 )
17811786
1782- assertAssetBalance (t .t , charlieTap , assetID , cents .Amount )
1787+ // Charlie used the entire amount of the asset to fund the channel, so
1788+ // tapd will report 0 balance. Tapd excludes the funding output from the
1789+ // balance.
1790+ assertAssetBalance (t .t , charlieTap , assetID , 0 )
17831791
17841792 // There should only be a single asset piece for Charlie, the one in the
17851793 // channel.
@@ -1894,3 +1902,202 @@ func testCustomChannelsLiquidityEdgeCases(_ context.Context,
18941902
18951903 logBalance (t .t , nodes , assetID , "after giant asset payment" )
18961904}
1905+
1906+ // testCustomChannelsBalanceConsistency is a test that test the balance .
1907+ func testCustomChannelsBalanceConsistency (_ context.Context ,
1908+ net * NetworkHarness , t * harnessTest ) {
1909+
1910+ ctxb := context .Background ()
1911+ lndArgs := slices .Clone (lndArgsTemplate )
1912+ litdArgs := slices .Clone (litdArgsTemplate )
1913+
1914+ zane , err := net .NewNode (
1915+ t .t , "Zane" , lndArgs , false , true , litdArgs ... ,
1916+ )
1917+ require .NoError (t .t , err )
1918+
1919+ litdArgs = append (litdArgs , fmt .Sprintf (
1920+ "--taproot-assets.proofcourieraddr=%s://%s" ,
1921+ proof .UniverseRpcCourierType , zane .Cfg .LitAddr (),
1922+ ))
1923+
1924+ charlie , err := net .NewNode (
1925+ t .t , "Charlie" , lndArgs , false , true , litdArgs ... ,
1926+ )
1927+ require .NoError (t .t , err )
1928+ dave , err := net .NewNode (t .t , "Dave" , lndArgs , false , true , litdArgs ... )
1929+ require .NoError (t .t , err )
1930+
1931+ nodes := []* HarnessNode {charlie , dave }
1932+ connectAllNodes (t .t , net , nodes )
1933+ fundAllNodes (t .t , net , nodes )
1934+
1935+ charlieTap := newTapClient (t .t , charlie )
1936+ daveTap := newTapClient (t .t , dave )
1937+ universeTap := newTapClient (t .t , zane )
1938+
1939+ // Mint an asset on Charlie and sync Dave to Charlie as the universe.
1940+ mintedAssets := itest .MintAssetsConfirmBatch (
1941+ t .t , t .lndHarness .Miner .Client , charlieTap ,
1942+ []* mintrpc.MintAssetRequest {
1943+ {
1944+ Asset : itestAsset ,
1945+ },
1946+ },
1947+ )
1948+ cents := mintedAssets [0 ]
1949+ assetID := cents .AssetGenesis .AssetId
1950+ var groupKey []byte
1951+ if cents .AssetGroup != nil {
1952+ groupKey = cents .AssetGroup .TweakedGroupKey
1953+ }
1954+
1955+ t .Logf ("Minted %d lightning cents, syncing universes..." , cents .Amount )
1956+ syncUniverses (t .t , charlieTap , dave )
1957+ t .Logf ("Universes synced between all nodes, distributing assets..." )
1958+
1959+ charlieBalance := cents .Amount
1960+
1961+ // Charlie should have a single balance output with the full balance.
1962+ assertAssetBalance (t .t , charlieTap , assetID , cents .Amount )
1963+
1964+ // The script key should be local to charlie, and the script key should
1965+ // be known. It is after all the asset he just minted himself.
1966+ scriptKeyLocal := true
1967+ scriptKeyKnown := false
1968+ scriptKeyHasScriptPath := false
1969+
1970+ scriptKey , err := schnorr .ParsePubKey (cents .ScriptKey [1 :])
1971+ require .NoError (t .t , err )
1972+ assertAssetExists (
1973+ t .t , charlieTap , assetID , charlieBalance ,
1974+ scriptKey , scriptKeyLocal , scriptKeyKnown ,
1975+ scriptKeyHasScriptPath ,
1976+ )
1977+
1978+ fundingScriptTree := tapscript .NewFundingScriptTree ()
1979+ fundingScriptKey := fundingScriptTree .TaprootKey
1980+ fundingScriptTreeBytes := fundingScriptKey .SerializeCompressed ()
1981+
1982+ fundRespCD , err := charlieTap .FundChannel (
1983+ ctxb , & tchrpc.FundChannelRequest {
1984+ AssetAmount : charlieBalance ,
1985+ AssetId : assetID ,
1986+ PeerPubkey : daveTap .node .PubKey [:],
1987+ FeeRateSatPerVbyte : 5 ,
1988+ PushSat : 0 ,
1989+ },
1990+ )
1991+ require .NoError (t .t , err )
1992+ t .Logf ("Funded channel between Charlie and Dave: %v" , fundRespCD )
1993+
1994+ // Make sure the pending channel shows up in the list and has the
1995+ // custom records set as JSON.
1996+ assertPendingChannels (
1997+ t .t , charlieTap .node , assetID , 1 , charlieBalance , 0 ,
1998+ )
1999+
2000+ // Let's confirm the channel.
2001+ mineBlocks (t , net , 6 , 1 )
2002+
2003+ // Tapd should not report any balance for Charlie, since the asset is
2004+ // used in a funding transaction. It should also not report any balance
2005+ // for Dave. All those balances are reported through channel balances.
2006+ assertAssetBalance (t .t , charlieTap , assetID , 0 )
2007+ assertAssetBalance (t .t , daveTap , assetID , 0 )
2008+
2009+ // There should only be a single asset piece for Charlie, the one in the
2010+ // channel.
2011+ assertNumAssetOutputs (t .t , charlieTap , assetID , 1 )
2012+
2013+ // The script key should now not be local anymore, since he funded a
2014+ // channel with it. Charlie does still know the script key though.
2015+ scriptKeyLocal = false
2016+ scriptKeyKnown = true
2017+ scriptKeyHasScriptPath = true
2018+ assertAssetExists (
2019+ t .t , charlieTap , assetID , charlieBalance ,
2020+ fundingScriptKey , scriptKeyLocal , scriptKeyKnown ,
2021+ scriptKeyHasScriptPath ,
2022+ )
2023+
2024+ // Assert that the proofs for both channels has been uploaded to the
2025+ // designated Universe server.
2026+ assertUniverseProofExists (
2027+ t .t , universeTap , assetID , groupKey , fundingScriptTreeBytes ,
2028+ fmt .Sprintf ("%v:%v" , fundRespCD .Txid , fundRespCD .OutputIndex ),
2029+ )
2030+
2031+ // Make sure the channel shows the correct asset information.
2032+ assertAssetChan (
2033+ t .t , charlieTap .node , daveTap .node , charlieBalance , assetID ,
2034+ )
2035+
2036+ logBalance (t .t , nodes , assetID , "initial" )
2037+
2038+ // Normal case.
2039+ // Send 500 assets from Charlie to Dave.
2040+ sendAssetKeySendPayment (
2041+ t .t , charlie , dave , 500 , assetID ,
2042+ fn .None [int64 ](), lnrpc .Payment_SUCCEEDED ,
2043+ fn .None [lnrpc.PaymentFailureReason ](),
2044+ )
2045+
2046+ logBalance (t .t , nodes , assetID , "after 500 assets" )
2047+
2048+ // Tapd stould still not report balances for Charlie and Dave, since
2049+ // they are still locked up in the funding transaction.
2050+ assertAssetBalance (t .t , charlieTap , assetID , 0 )
2051+ assertAssetBalance (t .t , daveTap , assetID , 0 )
2052+
2053+ // Send 10k sats from Charlie to Dave. Dave needs the sats to be able to
2054+ // send assets.
2055+ sendKeySendPayment (t .t , charlie , dave , 10000 )
2056+
2057+ // Now Dave tries to send 250 assets.
2058+ sendAssetKeySendPayment (
2059+ t .t , dave , charlie , 250 , assetID ,
2060+ fn .None [int64 ](), lnrpc .Payment_SUCCEEDED ,
2061+ fn .None [lnrpc.PaymentFailureReason ](),
2062+ )
2063+
2064+ logBalance (t .t , nodes , assetID , "after 250 sats backwards" )
2065+
2066+ // Tapd stould still not report balances for Charlie and Dave, since
2067+ // they are still locked up in the funding transaction.
2068+ assertAssetBalance (t .t , charlieTap , assetID , 0 )
2069+ assertAssetBalance (t .t , daveTap , assetID , 0 )
2070+
2071+ // We will now close the channel.
2072+ t .Logf ("Close the channel between Charlie and Dave..." )
2073+ charlieChanPoint := & lnrpc.ChannelPoint {
2074+ OutputIndex : uint32 (fundRespCD .OutputIndex ),
2075+ FundingTxid : & lnrpc.ChannelPoint_FundingTxidStr {
2076+ FundingTxidStr : fundRespCD .Txid ,
2077+ },
2078+ }
2079+
2080+ closeChannelAndAssert (t , net , charlie , charlieChanPoint , false )
2081+
2082+ // Charlie should have a single balance output with the balance 250 less
2083+ // than the total amount minted.
2084+ assertAssetBalance (t .t , charlieTap , assetID , charlieBalance - 250 )
2085+ assertAssetBalance (t .t , daveTap , assetID , 250 )
2086+
2087+ // The script key should now be local to both Charlie and Dave, since
2088+ // the channel was closed.
2089+ scriptKeyLocal = true
2090+ scriptKeyKnown = true
2091+ scriptKeyHasScriptPath = false
2092+ assertAssetExists (
2093+ t .t , charlieTap , assetID , charlieBalance - 250 ,
2094+ nil , scriptKeyLocal , scriptKeyKnown , scriptKeyHasScriptPath ,
2095+ )
2096+ assertAssetExists (
2097+ t .t , daveTap , assetID , 250 ,
2098+ nil , scriptKeyLocal , scriptKeyKnown , scriptKeyHasScriptPath ,
2099+ )
2100+
2101+ assertNumAssetOutputs (t .t , charlieTap , assetID , 1 )
2102+ assertNumAssetOutputs (t .t , daveTap , assetID , 1 )
2103+ }
0 commit comments