@@ -5,10 +5,10 @@ import (
55 "context"
66 "encoding/hex"
77
8+ "github.com/btcsuite/btcd/wire"
89 taprootassets "github.com/lightninglabs/taproot-assets"
910 "github.com/lightninglabs/taproot-assets/address"
1011 "github.com/lightninglabs/taproot-assets/asset"
11- "github.com/lightninglabs/taproot-assets/tapfreighter"
1212 "github.com/lightninglabs/taproot-assets/tappsbt"
1313 "github.com/lightninglabs/taproot-assets/taprpc"
1414 wrpc "github.com/lightninglabs/taproot-assets/taprpc/assetwalletrpc"
@@ -111,23 +111,7 @@ func testBurnAssets(t *harnessTest) {
111111 t .t , t .tapd , simpleAssetGen .AssetId , simpleAsset .Amount ,
112112 )
113113
114- // Test case 1: We'll now try to the exact amount of the largest output,
115- // which should still select exactly that one largest output, which is
116- // located alone in an anchor output. When attempting to burn this, we
117- // should get an error saying that we cannot completely burn all assets
118- // in an output.
119- _ , err = t .tapd .BurnAsset (ctxt , & taprpc.BurnAssetRequest {
120- Asset : & taprpc.BurnAssetRequest_AssetId {
121- AssetId : simpleAssetID [:],
122- },
123- AmountToBurn : outputAmounts [3 ],
124- ConfirmationText : taprootassets .AssetBurnConfirmationText ,
125- })
126- require .ErrorContains (
127- t .t , err , tapfreighter .ErrFullBurnNotSupported .Error (),
128- )
129-
130- // Test case 2: We'll now try to burn a small amount of assets, which
114+ // Test case 1: We'll now try to burn a small amount of assets, which
131115 // should select the largest output, which is located alone in an anchor
132116 // output.
133117 const (
@@ -208,7 +192,7 @@ func testBurnAssets(t *harnessTest) {
208192 AssertNonInteractiveRecvComplete (t .t , t .tapd , 1 )
209193 AssertReceiveEvents (t .t , fullSendAddr , stream )
210194
211- // Test case 3 : Burn all assets of one asset ID (in this case a single
195+ // Test case 2 : Burn all assets of one asset ID (in this case a single
212196 // collectible from the original mint TX), while there are other,
213197 // passive assets in the anchor output.
214198 burnResp , err = t .tapd .BurnAsset (ctxt , & taprpc.BurnAssetRequest {
@@ -237,7 +221,7 @@ func testBurnAssets(t *harnessTest) {
237221 WithScriptKeyType (asset .ScriptKeyBurn ),
238222 )
239223
240- // Test case 4 : Burn assets from multiple inputs. This will select the
224+ // Test case 3 : Burn assets from multiple inputs. This will select the
241225 // two largest inputs we have, the one over 1500 we sent above and the
242226 // 1200 from the initial fan out transfer.
243227 const changeAmt = 300
@@ -283,7 +267,7 @@ func testBurnAssets(t *harnessTest) {
283267 require .NoError (t .t , err )
284268 t .Logf ("All assets before last burn: %v" , assets )
285269
286- // Test case 5 : Burn some units of a grouped asset. We start by making
270+ // Test case 4 : Burn some units of a grouped asset. We start by making
287271 // sure we still have the full balance before burning.
288272 AssertBalanceByID (
289273 t .t , t .tapd , simpleGroupGen .AssetId , simpleGroup .Amount ,
@@ -344,7 +328,7 @@ func testBurnAssets(t *harnessTest) {
344328
345329 require .Equal (t .t , groupBurn .Note , "" )
346330
347- // Test case 6 : Burn the single unit of a grouped collectible. We start
331+ // Test case 5 : Burn the single unit of a grouped collectible. We start
348332 // by making sure we still have the full balance before burning.
349333 AssertBalanceByID (
350334 t .t , t .tapd , simpleGroupCollectGen .AssetId ,
@@ -524,3 +508,120 @@ func testBurnGroupedAssets(t *harnessTest) {
524508 require .Equal (t .t , burnNote , burn .Note )
525509 require .Equal (t .t , assetGroupKey , burn .TweakedGroupKey )
526510}
511+
512+ // testFullBurnUTXO tests that we can burn the full amount of an asset UTXO.
513+ func testFullBurnUTXO (t * harnessTest ) {
514+ minerClient := t .lndHarness .Miner ().Client
515+ ctxb := context .Background ()
516+ ctxt , cancel := context .WithTimeout (ctxb , defaultWaitTimeout )
517+ defer cancel ()
518+
519+ // Test 1: Burn the full amount of a simple asset.
520+ rpcAssets := MintAssetsConfirmBatch (
521+ t .t , minerClient , t .tapd , []* mintrpc.MintAssetRequest {
522+ simpleAssets [0 ],
523+ },
524+ )
525+ simpleAsset := rpcAssets [0 ]
526+ simpleAssetGen := simpleAsset .AssetGenesis
527+ var simpleAssetID [32 ]byte
528+ copy (simpleAssetID [:], simpleAssetGen .AssetId )
529+
530+ AssertBalanceByID (
531+ t .t , t .tapd , simpleAssetGen .AssetId , simpleAsset .Amount ,
532+ )
533+
534+ // Perform a full burn of the asset.
535+ fullBurnAmt := simpleAsset .Amount
536+ burnResp , err := t .tapd .BurnAsset (ctxt , & taprpc.BurnAssetRequest {
537+ Asset : & taprpc.BurnAssetRequest_AssetId {
538+ AssetId : simpleAssetID [:],
539+ },
540+ AmountToBurn : fullBurnAmt ,
541+ ConfirmationText : taprootassets .AssetBurnConfirmationText ,
542+ })
543+ require .NoError (t .t , err )
544+
545+ AssertAssetOutboundTransferWithOutputs (
546+ t .t , minerClient , t .tapd , burnResp .BurnTransfer ,
547+ [][]byte {simpleAssetGen .AssetId },
548+ []uint64 {fullBurnAmt }, 0 , 1 , 1 , true ,
549+ )
550+ AssertBalanceByID (t .t , t .tapd , simpleAssetGen .AssetId , 0 )
551+
552+ // Export and verify the burn proof for the simple asset.
553+ wop , err := wire .NewOutPointFromString (
554+ burnResp .BurnTransfer .Outputs [0 ].Anchor .Outpoint ,
555+ )
556+ require .NoError (t .t , err )
557+ outpoint := & taprpc.OutPoint {Txid : wop .Hash [:], OutputIndex : wop .Index }
558+
559+ proofResp := ExportProofFile (
560+ t .t , t .tapd ,
561+ burnResp .BurnProof .Asset .AssetGenesis .AssetId ,
562+ burnResp .BurnProof .Asset .ScriptKey ,
563+ outpoint ,
564+ )
565+ verifyResp , err := t .tapd .VerifyProof (ctxt , & taprpc.ProofFile {
566+ RawProofFile : proofResp .RawProofFile ,
567+ })
568+ require .NoError (t .t , err )
569+ require .True (t .t , verifyResp .Valid )
570+
571+ // Test 2: Burn the full amount of a collectible asset.
572+ rpcAssets = MintAssetsConfirmBatch (
573+ t .t , minerClient , t .tapd , []* mintrpc.MintAssetRequest {
574+ simpleAssets [1 ],
575+ },
576+ )
577+ collectibleAsset := rpcAssets [0 ]
578+ collectibleAssetGen := collectibleAsset .AssetGenesis
579+ var collectibleAssetID [32 ]byte
580+ copy (collectibleAssetID [:], collectibleAssetGen .AssetId )
581+
582+ AssertBalanceByID (
583+ t .t , t .tapd , collectibleAssetGen .AssetId ,
584+ collectibleAsset .Amount ,
585+ )
586+
587+ fullBurnAmt = collectibleAsset .Amount
588+ burnResp , err = t .tapd .BurnAsset (ctxt , & taprpc.BurnAssetRequest {
589+ Asset : & taprpc.BurnAssetRequest_AssetId {
590+ AssetId : collectibleAssetID [:],
591+ },
592+ AmountToBurn : fullBurnAmt ,
593+ ConfirmationText : taprootassets .AssetBurnConfirmationText ,
594+ })
595+ require .NoError (t .t , err )
596+
597+ AssertAssetOutboundTransferWithOutputs (
598+ t .t , minerClient , t .tapd , burnResp .BurnTransfer ,
599+ [][]byte {collectibleAssetID [:]},
600+ []uint64 {fullBurnAmt }, 1 , 2 , 1 , true ,
601+ )
602+ AssertBalanceByID (t .t , t .tapd , collectibleAssetID [:], 0 )
603+
604+ // Export and verify the burn proof for the collectible.
605+ wop , err = wire .NewOutPointFromString (
606+ burnResp .BurnTransfer .Outputs [0 ].Anchor .Outpoint ,
607+ )
608+ require .NoError (t .t , err )
609+ outpoint = & taprpc.OutPoint {Txid : wop .Hash [:], OutputIndex : wop .Index }
610+
611+ proofResp = ExportProofFile (
612+ t .t , t .tapd ,
613+ burnResp .BurnProof .Asset .AssetGenesis .AssetId ,
614+ burnResp .BurnProof .Asset .ScriptKey ,
615+ outpoint ,
616+ )
617+ verifyResp , err = t .tapd .VerifyProof (ctxt , & taprpc.ProofFile {
618+ RawProofFile : proofResp .RawProofFile ,
619+ })
620+ require .NoError (t .t , err )
621+ require .True (t .t , verifyResp .Valid )
622+
623+ // Verify that we have 2 burns.
624+ burns := AssertNumBurns (t .t , t .tapd , 2 , nil )
625+ require .Equal (t .t , simpleAssetGen .AssetId , burns [0 ].AssetId )
626+ require .Equal (t .t , collectibleAssetGen .AssetId , burns [1 ].AssetId )
627+ }
0 commit comments