@@ -120,27 +120,25 @@ func testBurnAssets(t *harnessTest) {
120120 )
121121
122122 burnResp , err := t .tapd .BurnAsset (ctxt , & taprpc.BurnAssetRequest {
123- Asset : & taprpc.BurnAssetRequest_AssetId {
124- AssetId : simpleAssetID [:],
123+ AssetSpecifier : & taprpc.AssetSpecifier {
124+ Id : & taprpc.AssetSpecifier_AssetId {
125+ AssetId : simpleAssetID [:],
126+ },
125127 },
126128 AmountToBurn : burnAmt ,
127129 Note : burnNote ,
128130 ConfirmationText : taprootassets .AssetBurnConfirmationText ,
129131 })
130132 require .NoError (t .t , err )
131133
132- burnRespJSON , err := formatProtoJSON (burnResp )
133- require .NoError (t .t , err )
134- t .Logf ("Got response from burning %d units: %v" , burnAmt , burnRespJSON )
135-
136134 AssertAssetOutboundTransferWithOutputs (
137135 t .t , minerClient , t .tapd , burnResp .BurnTransfer ,
138136 [][]byte {simpleAssetGen .AssetId },
139137 []uint64 {outputAmounts [3 ] - burnAmt , burnAmt }, 1 , 2 , 2 , true ,
140138 )
141139
142140 // We'll now assert that the burned asset has the correct state.
143- burnedAsset := burnResp .BurnProof .Asset
141+ burnedAsset := burnResp .BurnProofs [ 0 ] .Asset
144142 allAssets , err := t .tapd .ListAssets (ctxt , & taprpc.ListAssetRequest {
145143 IncludeSpent : true ,
146144 ScriptKeyType : allScriptKeysQuery ,
@@ -196,18 +194,16 @@ func testBurnAssets(t *harnessTest) {
196194 // collectible from the original mint TX), while there are other,
197195 // passive assets in the anchor output.
198196 burnResp , err = t .tapd .BurnAsset (ctxt , & taprpc.BurnAssetRequest {
199- Asset : & taprpc.BurnAssetRequest_AssetId {
200- AssetId : simpleCollectibleGen .AssetId ,
197+ AssetSpecifier : & taprpc.AssetSpecifier {
198+ Id : & taprpc.AssetSpecifier_AssetId {
199+ AssetId : simpleCollectibleGen .AssetId ,
200+ },
201201 },
202202 AmountToBurn : simpleCollectible .Amount ,
203203 ConfirmationText : taprootassets .AssetBurnConfirmationText ,
204204 })
205205 require .NoError (t .t , err )
206206
207- burnRespJSON , err = formatProtoJSON (burnResp )
208- require .NoError (t .t , err )
209- t .Logf ("Got response from burning all units: %v" , burnRespJSON )
210-
211207 AssertAssetOutboundTransferWithOutputs (
212208 t .t , minerClient , t .tapd , burnResp .BurnTransfer ,
213209 [][]byte {simpleCollectibleGen .AssetId }, []uint64 {1 }, 3 , 4 , 1 ,
@@ -227,19 +223,16 @@ func testBurnAssets(t *harnessTest) {
227223 const changeAmt = 300
228224 multiBurnAmt := outputAmounts [2 ] + secondSendAmt - changeAmt
229225 burnResp , err = t .tapd .BurnAsset (ctxt , & taprpc.BurnAssetRequest {
230- Asset : & taprpc.BurnAssetRequest_AssetId {
231- AssetId : simpleAssetGen .AssetId ,
226+ AssetSpecifier : & taprpc.AssetSpecifier {
227+ Id : & taprpc.AssetSpecifier_AssetId {
228+ AssetId : simpleAssetGen .AssetId ,
229+ },
232230 },
233231 AmountToBurn : multiBurnAmt ,
234232 ConfirmationText : taprootassets .AssetBurnConfirmationText ,
235233 })
236234 require .NoError (t .t , err )
237235
238- burnRespJSON , err = formatProtoJSON (burnResp )
239- require .NoError (t .t , err )
240- t .Logf ("Got response from burning units from multiple inputs: %v" ,
241- burnRespJSON )
242-
243236 AssertAssetOutboundTransferWithOutputs (
244237 t .t , minerClient , t .tapd , burnResp .BurnTransfer ,
245238 [][]byte {simpleAssetGen .AssetId },
@@ -259,33 +252,27 @@ func testBurnAssets(t *harnessTest) {
259252 WithScriptKeyType (asset .ScriptKeyBurn ),
260253 )
261254
262- resp , err : = t .tapd .ListAssets (ctxt , & taprpc.ListAssetRequest {
255+ _ , err = t .tapd .ListAssets (ctxt , & taprpc.ListAssetRequest {
263256 IncludeSpent : true ,
264257 })
265258 require .NoError (t .t , err )
266- assets , err := formatProtoJSON (resp )
267- require .NoError (t .t , err )
268- t .Logf ("All assets before last burn: %v" , assets )
269259
270260 // Test case 4: Burn some units of a grouped asset. We start by making
271261 // sure we still have the full balance before burning.
272262 AssertBalanceByID (
273263 t .t , t .tapd , simpleGroupGen .AssetId , simpleGroup .Amount ,
274264 )
275265 burnResp , err = t .tapd .BurnAsset (ctxt , & taprpc.BurnAssetRequest {
276- Asset : & taprpc.BurnAssetRequest_AssetId {
277- AssetId : simpleGroupGen .AssetId ,
266+ AssetSpecifier : & taprpc.AssetSpecifier {
267+ Id : & taprpc.AssetSpecifier_AssetId {
268+ AssetId : simpleGroupGen .AssetId ,
269+ },
278270 },
279271 AmountToBurn : burnAmt ,
280272 ConfirmationText : taprootassets .AssetBurnConfirmationText ,
281273 })
282274 require .NoError (t .t , err )
283275
284- burnRespJSON , err = formatProtoJSON (burnResp )
285- require .NoError (t .t , err )
286- t .Logf ("Got response from burning units from grouped asset: %v" ,
287- burnRespJSON )
288-
289276 AssertAssetOutboundTransferWithOutputs (
290277 t .t , minerClient , t .tapd , burnResp .BurnTransfer ,
291278 [][]byte {simpleGroupGen .AssetId },
@@ -295,10 +282,12 @@ func testBurnAssets(t *harnessTest) {
295282 t .t , t .tapd , simpleGroupGen .AssetId , simpleGroup .Amount - burnAmt ,
296283 )
297284
285+ // Depending on passive re-anchoring behavior, earlier burn outputs
286+ // might become spent when inputs are consolidated. We assert only
287+ // currently unspent burn outputs here.
298288 AssertBalances (
299289 t .t , t .tapd ,
300- burnAmt + simpleCollectible .Amount + multiBurnAmt + burnAmt ,
301- WithNumUtxos (4 ), WithNumAnchorUtxos (4 ),
290+ burnAmt + multiBurnAmt + burnAmt ,
302291 WithScriptKeyType (asset .ScriptKeyBurn ),
303292 )
304293
@@ -335,19 +324,16 @@ func testBurnAssets(t *harnessTest) {
335324 simpleGroupCollect .Amount ,
336325 )
337326 burnResp , err = t .tapd .BurnAsset (ctxt , & taprpc.BurnAssetRequest {
338- Asset : & taprpc.BurnAssetRequest_AssetId {
339- AssetId : simpleGroupCollectGen .AssetId ,
327+ AssetSpecifier : & taprpc.AssetSpecifier {
328+ Id : & taprpc.AssetSpecifier_AssetId {
329+ AssetId : simpleGroupCollectGen .AssetId ,
330+ },
340331 },
341332 AmountToBurn : 1 ,
342333 ConfirmationText : taprootassets .AssetBurnConfirmationText ,
343334 })
344335 require .NoError (t .t , err )
345336
346- burnRespJSON , err = formatProtoJSON (burnResp )
347- require .NoError (t .t , err )
348- t .Logf ("Got response from burning units from grouped asset: %v" ,
349- burnRespJSON )
350-
351337 AssertAssetOutboundTransferWithOutputs (
352338 t .t , minerClient , t .tapd , burnResp .BurnTransfer ,
353339 [][]byte {simpleGroupCollectGen .AssetId }, []uint64 {1 }, 6 , 7 , 1 ,
@@ -357,8 +343,7 @@ func testBurnAssets(t *harnessTest) {
357343
358344 AssertBalances (
359345 t .t , t .tapd ,
360- burnAmt + simpleCollectible .Amount + multiBurnAmt + burnAmt + 1 ,
361- WithNumUtxos (5 ), WithNumAnchorUtxos (5 ),
346+ burnAmt + multiBurnAmt + burnAmt + 1 ,
362347 WithScriptKeyType (asset .ScriptKeyBurn ),
363348 )
364349
@@ -406,6 +391,7 @@ func testBurnGroupedAssets(t *harnessTest) {
406391
407392 var (
408393 firstMintResp = firstMintResponses [0 ]
394+ burnAssetID1 = firstMintResp .AssetGenesis .AssetId
409395 assetGroupKey = firstMintResp .AssetGroup .TweakedGroupKey
410396 )
411397
@@ -440,38 +426,39 @@ func testBurnGroupedAssets(t *harnessTest) {
440426 assetGroup := assetGroups .Groups [encodedGroupKey ]
441427 require .Len (t .t , assetGroup .Assets , 2 )
442428
443- // Burn some amount of the second asset.
429+ totalAmt := firstMintResp .Amount + secondMintResp .Amount
430+ AssertBalanceByGroup (t .t , t .tapd , encodedGroupKey , totalAmt )
431+
432+ // Test case 1: Burn by asset id.
444433 var (
445- burnAssetID = secondMintResp .AssetGenesis .AssetId
434+ burnAssetID2 = secondMintResp .AssetGenesis .AssetId
446435
447436 preBurnAmt = secondMintResp .Amount
448437 burnAmt = uint64 (10 )
449438 postBurnAmt = preBurnAmt - burnAmt
450439 )
451440
452441 burnResp , err := t .tapd .BurnAsset (ctxb , & taprpc.BurnAssetRequest {
453- Asset : & taprpc.BurnAssetRequest_AssetId {
454- AssetId : burnAssetID ,
442+ AssetSpecifier : & taprpc.AssetSpecifier {
443+ Id : & taprpc.AssetSpecifier_AssetId {
444+ AssetId : burnAssetID2 ,
445+ },
455446 },
456447 AmountToBurn : burnAmt ,
457448 Note : burnNote ,
458449 ConfirmationText : taprootassets .AssetBurnConfirmationText ,
459450 })
460451 require .NoError (t .t , err )
461452
462- burnRespJSON , err := formatProtoJSON (burnResp )
463- require .NoError (t .t , err )
464- t .Logf ("Got response from burning %d units: %v" , burnAmt , burnRespJSON )
465-
466453 // Assert that the asset burn transfer occurred correctly.
467454 AssertAssetOutboundTransferWithOutputs (
468455 t .t , miner , t .tapd , burnResp .BurnTransfer ,
469- [][]byte {burnAssetID }, []uint64 {postBurnAmt , burnAmt }, 0 , 1 , 2 ,
456+ [][]byte {burnAssetID2 }, []uint64 {postBurnAmt , burnAmt }, 0 , 1 , 2 ,
470457 true ,
471458 )
472459
473460 // Ensure that the burnt asset has the correct state.
474- burnedAsset := burnResp .BurnProof .Asset
461+ burnedAsset := burnResp .BurnProofs [ 0 ] .Asset
475462 allAssets , err := t .tapd .ListAssets (ctxb , & taprpc.ListAssetRequest {
476463 IncludeSpent : true ,
477464 ScriptKeyType : allScriptKeysQuery ,
@@ -486,7 +473,7 @@ func testBurnGroupedAssets(t *harnessTest) {
486473 )
487474
488475 // Our asset balance should have been decreased by the burned amount.
489- AssertBalanceByID (t .t , t .tapd , burnAssetID , postBurnAmt )
476+ AssertBalanceByID (t .t , t .tapd , burnAssetID2 , postBurnAmt )
490477
491478 // Confirm that the minted asset group still contains two assets.
492479 assetGroups , err = t .tapd .ListGroups (ctxb , & taprpc.ListGroupsRequest {})
@@ -507,6 +494,48 @@ func testBurnGroupedAssets(t *harnessTest) {
507494 require .Equal (t .t , burnAmt , burn .Amount )
508495 require .Equal (t .t , burnNote , burn .Note )
509496 require .Equal (t .t , assetGroupKey , burn .TweakedGroupKey )
497+
498+ // Test case 2: Burn by group key to we select multiple inputs.
499+ burnAmt = totalAmt - burnAmt - 1
500+ burnResp , err = t .tapd .BurnAsset (ctxb , & taprpc.BurnAssetRequest {
501+ AssetSpecifier : & taprpc.AssetSpecifier {
502+ Id : & taprpc.AssetSpecifier_GroupKey {
503+ GroupKey : assetGroupKey ,
504+ },
505+ },
506+ AmountToBurn : burnAmt ,
507+ ConfirmationText : taprootassets .AssetBurnConfirmationText ,
508+ })
509+ require .NoError (t .t , err )
510+
511+ // When burning by group key with multiple inputs, the coin selection
512+ // can vary. We verify that:
513+ // 1. There are 3 outputs total (1 change + 2 burn outputs)
514+ // 2. The sum of all outputs equals the total remaining balance
515+ // 3. One output is the change amount (1 unit)
516+ amounts := make ([]uint64 , len (burnResp .BurnTransfer .Outputs ))
517+ for i , out := range burnResp .BurnTransfer .Outputs {
518+ amounts [i ] = out .Amount
519+ }
520+ require .Len (t .t , amounts , 3 )
521+
522+ // Sum should equal total balance before this burn.
523+ totalBeforeBurn := firstMintResp .Amount + postBurnAmt
524+ actualSum := uint64 (0 )
525+ for _ , amt := range amounts {
526+ actualSum += amt
527+ }
528+ require .Equal (t .t , totalBeforeBurn , actualSum )
529+
530+ // One output should be the change (1 unit).
531+ require .Contains (t .t , amounts , uint64 (1 ))
532+
533+ AssertAssetOutboundTransferWithOutputs (
534+ t .t , miner , t .tapd , burnResp .BurnTransfer ,
535+ [][]byte {burnAssetID1 , burnAssetID2 },
536+ amounts , 1 , 2 , 3 , true ,
537+ )
538+ AssertBalanceByGroup (t .t , t .tapd , encodedGroupKey , 1 )
510539}
511540
512541// testFullBurnUTXO tests that we can burn the full amount of an asset UTXO.
@@ -534,8 +563,10 @@ func testFullBurnUTXO(t *harnessTest) {
534563 // Perform a full burn of the asset.
535564 fullBurnAmt := simpleAsset .Amount
536565 burnResp , err := t .tapd .BurnAsset (ctxt , & taprpc.BurnAssetRequest {
537- Asset : & taprpc.BurnAssetRequest_AssetId {
538- AssetId : simpleAssetID [:],
566+ AssetSpecifier : & taprpc.AssetSpecifier {
567+ Id : & taprpc.AssetSpecifier_AssetId {
568+ AssetId : simpleAssetID [:],
569+ },
539570 },
540571 AmountToBurn : fullBurnAmt ,
541572 ConfirmationText : taprootassets .AssetBurnConfirmationText ,
@@ -558,8 +589,8 @@ func testFullBurnUTXO(t *harnessTest) {
558589
559590 proofResp := ExportProofFile (
560591 t .t , t .tapd ,
561- burnResp .BurnProof .Asset .AssetGenesis .AssetId ,
562- burnResp .BurnProof .Asset .ScriptKey ,
592+ burnResp .BurnProofs [ 0 ] .Asset .AssetGenesis .AssetId ,
593+ burnResp .BurnProofs [ 0 ] .Asset .ScriptKey ,
563594 outpoint ,
564595 )
565596 verifyResp , err := t .tapd .VerifyProof (ctxt , & taprpc.ProofFile {
@@ -586,8 +617,10 @@ func testFullBurnUTXO(t *harnessTest) {
586617
587618 fullBurnAmt = collectibleAsset .Amount
588619 burnResp , err = t .tapd .BurnAsset (ctxt , & taprpc.BurnAssetRequest {
589- Asset : & taprpc.BurnAssetRequest_AssetId {
590- AssetId : collectibleAssetID [:],
620+ AssetSpecifier : & taprpc.AssetSpecifier {
621+ Id : & taprpc.AssetSpecifier_AssetId {
622+ AssetId : collectibleAssetID [:],
623+ },
591624 },
592625 AmountToBurn : fullBurnAmt ,
593626 ConfirmationText : taprootassets .AssetBurnConfirmationText ,
@@ -610,8 +643,8 @@ func testFullBurnUTXO(t *harnessTest) {
610643
611644 proofResp = ExportProofFile (
612645 t .t , t .tapd ,
613- burnResp .BurnProof .Asset .AssetGenesis .AssetId ,
614- burnResp .BurnProof .Asset .ScriptKey ,
646+ burnResp .BurnProofs [ 0 ] .Asset .AssetGenesis .AssetId ,
647+ burnResp .BurnProofs [ 0 ] .Asset .ScriptKey ,
615648 outpoint ,
616649 )
617650 verifyResp , err = t .tapd .VerifyProof (ctxt , & taprpc.ProofFile {
0 commit comments