|
8 | 8 | taprootassets "github.com/lightninglabs/taproot-assets" |
9 | 9 | "github.com/lightninglabs/taproot-assets/address" |
10 | 10 | "github.com/lightninglabs/taproot-assets/asset" |
11 | | - "github.com/lightninglabs/taproot-assets/tapfreighter" |
12 | 11 | "github.com/lightninglabs/taproot-assets/tappsbt" |
13 | 12 | "github.com/lightninglabs/taproot-assets/taprpc" |
14 | 13 | wrpc "github.com/lightninglabs/taproot-assets/taprpc/assetwalletrpc" |
@@ -111,23 +110,7 @@ func testBurnAssets(t *harnessTest) { |
111 | 110 | t.t, t.tapd, simpleAssetGen.AssetId, simpleAsset.Amount, |
112 | 111 | ) |
113 | 112 |
|
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 |
131 | 114 | // should select the largest output, which is located alone in an anchor |
132 | 115 | // output. |
133 | 116 | const ( |
@@ -208,7 +191,7 @@ func testBurnAssets(t *harnessTest) { |
208 | 191 | AssertNonInteractiveRecvComplete(t.t, t.tapd, 1) |
209 | 192 | AssertReceiveEvents(t.t, fullSendAddr, stream) |
210 | 193 |
|
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 |
212 | 195 | // collectible from the original mint TX), while there are other, |
213 | 196 | // passive assets in the anchor output. |
214 | 197 | burnResp, err = t.tapd.BurnAsset(ctxt, &taprpc.BurnAssetRequest{ |
@@ -237,7 +220,7 @@ func testBurnAssets(t *harnessTest) { |
237 | 220 | WithScriptKeyType(asset.ScriptKeyBurn), |
238 | 221 | ) |
239 | 222 |
|
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 |
241 | 224 | // two largest inputs we have, the one over 1500 we sent above and the |
242 | 225 | // 1200 from the initial fan out transfer. |
243 | 226 | const changeAmt = 300 |
@@ -283,7 +266,7 @@ func testBurnAssets(t *harnessTest) { |
283 | 266 | require.NoError(t.t, err) |
284 | 267 | t.Logf("All assets before last burn: %v", assets) |
285 | 268 |
|
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 |
287 | 270 | // sure we still have the full balance before burning. |
288 | 271 | AssertBalanceByID( |
289 | 272 | t.t, t.tapd, simpleGroupGen.AssetId, simpleGroup.Amount, |
@@ -344,7 +327,7 @@ func testBurnAssets(t *harnessTest) { |
344 | 327 |
|
345 | 328 | require.Equal(t.t, groupBurn.Note, "") |
346 | 329 |
|
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 |
348 | 331 | // by making sure we still have the full balance before burning. |
349 | 332 | AssertBalanceByID( |
350 | 333 | t.t, t.tapd, simpleGroupCollectGen.AssetId, |
@@ -524,3 +507,83 @@ func testBurnGroupedAssets(t *harnessTest) { |
524 | 507 | require.Equal(t.t, burnNote, burn.Note) |
525 | 508 | require.Equal(t.t, assetGroupKey, burn.TweakedGroupKey) |
526 | 509 | } |
| 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 | +} |
0 commit comments