Skip to content

Commit ccc5d1f

Browse files
committed
itest: add test for full UTXO burns
1 parent de86b71 commit ccc5d1f

File tree

2 files changed

+89
-22
lines changed

2 files changed

+89
-22
lines changed

itest/burn_test.go

Lines changed: 85 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
taprootassets "github.com/lightninglabs/taproot-assets"
99
"github.com/lightninglabs/taproot-assets/address"
1010
"github.com/lightninglabs/taproot-assets/asset"
11-
"github.com/lightninglabs/taproot-assets/tapfreighter"
1211
"github.com/lightninglabs/taproot-assets/tappsbt"
1312
"github.com/lightninglabs/taproot-assets/taprpc"
1413
wrpc "github.com/lightninglabs/taproot-assets/taprpc/assetwalletrpc"
@@ -111,23 +110,7 @@ func testBurnAssets(t *harnessTest) {
111110
t.t, t.tapd, simpleAssetGen.AssetId, simpleAsset.Amount,
112111
)
113112

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
113+
// Test case 1: We'll now try to burn a small amount of assets, which
131114
// should select the largest output, which is located alone in an anchor
132115
// output.
133116
const (
@@ -208,7 +191,7 @@ func testBurnAssets(t *harnessTest) {
208191
AssertNonInteractiveRecvComplete(t.t, t.tapd, 1)
209192
AssertReceiveEvents(t.t, fullSendAddr, stream)
210193

211-
// Test case 3: Burn all assets of one asset ID (in this case a single
194+
// Test case 2: Burn all assets of one asset ID (in this case a single
212195
// collectible from the original mint TX), while there are other,
213196
// passive assets in the anchor output.
214197
burnResp, err = t.tapd.BurnAsset(ctxt, &taprpc.BurnAssetRequest{
@@ -237,7 +220,7 @@ func testBurnAssets(t *harnessTest) {
237220
WithScriptKeyType(asset.ScriptKeyBurn),
238221
)
239222

240-
// Test case 4: Burn assets from multiple inputs. This will select the
223+
// Test case 3: Burn assets from multiple inputs. This will select the
241224
// two largest inputs we have, the one over 1500 we sent above and the
242225
// 1200 from the initial fan out transfer.
243226
const changeAmt = 300
@@ -283,7 +266,7 @@ func testBurnAssets(t *harnessTest) {
283266
require.NoError(t.t, err)
284267
t.Logf("All assets before last burn: %v", assets)
285268

286-
// Test case 5: Burn some units of a grouped asset. We start by making
269+
// Test case 4: Burn some units of a grouped asset. We start by making
287270
// sure we still have the full balance before burning.
288271
AssertBalanceByID(
289272
t.t, t.tapd, simpleGroupGen.AssetId, simpleGroup.Amount,
@@ -344,7 +327,7 @@ func testBurnAssets(t *harnessTest) {
344327

345328
require.Equal(t.t, groupBurn.Note, "")
346329

347-
// Test case 6: Burn the single unit of a grouped collectible. We start
330+
// Test case 5: Burn the single unit of a grouped collectible. We start
348331
// by making sure we still have the full balance before burning.
349332
AssertBalanceByID(
350333
t.t, t.tapd, simpleGroupCollectGen.AssetId,
@@ -524,3 +507,83 @@ func testBurnGroupedAssets(t *harnessTest) {
524507
require.Equal(t.t, burnNote, burn.Note)
525508
require.Equal(t.t, assetGroupKey, burn.TweakedGroupKey)
526509
}
510+
511+
// testFullBurnUTXO tests that we can burn the full amount of an asset UTXO
512+
func testFullBurnUTXO(t *harnessTest) {
513+
minerClient := t.lndHarness.Miner().Client
514+
ctxb := context.Background()
515+
ctxt, cancel := context.WithTimeout(ctxb, defaultWaitTimeout)
516+
defer cancel()
517+
518+
rpcAssets := MintAssetsConfirmBatch(
519+
t.t, minerClient, t.tapd, []*mintrpc.MintAssetRequest{
520+
simpleAssets[0],
521+
},
522+
)
523+
simpleAsset := rpcAssets[0]
524+
simpleAssetGen := simpleAsset.AssetGenesis
525+
526+
var simpleAssetID [32]byte
527+
copy(simpleAssetID[:], simpleAssetGen.AssetId)
528+
529+
scriptKey1, anchorKeyDesc1 := DeriveKeys(t.t, t.tapd)
530+
scriptKey2, anchorKeyDesc2 := DeriveKeys(t.t, t.tapd)
531+
chainParams := &address.RegressionNetTap
532+
533+
// Create two outputs on different anchors.
534+
outputAmounts := []uint64{simpleAsset.Amount - 4200, 1200, 3000}
535+
vPkt := tappsbt.ForInteractiveSend(
536+
simpleAssetID, outputAmounts[1], scriptKey1,
537+
0, 0, 0, anchorKeyDesc1, asset.V0, chainParams,
538+
)
539+
tappsbt.AddOutput(
540+
vPkt, outputAmounts[2], scriptKey2, 1, anchorKeyDesc2, asset.V0,
541+
)
542+
543+
fundResp := fundPacket(t, t.tapd, vPkt)
544+
signResp, err := t.tapd.SignVirtualPsbt(
545+
ctxt, &wrpc.SignVirtualPsbtRequest{
546+
FundedPsbt: fundResp.FundedPsbt,
547+
},
548+
)
549+
require.NoError(t.t, err)
550+
sendResp, err := t.tapd.AnchorVirtualPsbts(
551+
ctxt, &wrpc.AnchorVirtualPsbtsRequest{
552+
VirtualPsbts: [][]byte{signResp.SignedPsbt},
553+
},
554+
)
555+
require.NoError(t.t, err)
556+
ConfirmAndAssertOutboundTransferWithOutputs(
557+
t.t, minerClient, t.tapd, sendResp, simpleAssetGen.AssetId,
558+
outputAmounts, 0, 1, 3,
559+
)
560+
561+
// Verify pre-burn balance.
562+
AssertBalanceByID(
563+
t.t, t.tapd, simpleAssetGen.AssetId, simpleAsset.Amount,
564+
)
565+
566+
// Perform a full burn of the isolated largest output (1200).
567+
fullBurnAmt := outputAmounts[2]
568+
burnResp, err := t.tapd.BurnAsset(ctxt, &taprpc.BurnAssetRequest{
569+
Asset: &taprpc.BurnAssetRequest_AssetId{
570+
AssetId: simpleAssetID[:],
571+
},
572+
AmountToBurn: fullBurnAmt,
573+
ConfirmationText: taprootassets.AssetBurnConfirmationText,
574+
})
575+
require.NoError(t.t, err)
576+
577+
// Expect burn output and tombstone split root.
578+
AssertAssetOutboundTransferWithOutputs(
579+
t.t, minerClient, t.tapd, burnResp.BurnTransfer,
580+
[][]byte{simpleAssetGen.AssetId},
581+
[]uint64{fullBurnAmt, 0}, 1, 2, 2, true,
582+
)
583+
584+
// Balance reflects the full burn amount.
585+
AssertBalanceByID(
586+
t.t, t.tapd, simpleAssetGen.AssetId,
587+
simpleAsset.Amount-fullBurnAmt,
588+
)
589+
}

itest/test_list_on_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,10 @@ var allTestCases = []*testCase{
309309
name: "burn grouped assets",
310310
test: testBurnGroupedAssets,
311311
},
312+
{
313+
name: "full burn assets",
314+
test: testFullBurnUTXO,
315+
},
312316
{
313317
name: "federation sync config",
314318
test: testFederationSyncConfig,

0 commit comments

Comments
 (0)