Skip to content

Commit d4b078a

Browse files
committed
test: add zero_value_anchor_test.go
Add the missing integration test for zero-value UTXO sweeping functionality.
1 parent 6fe11a5 commit d4b078a

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed

itest/zero_value_anchor_test.go

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package itest
2+
3+
import (
4+
"context"
5+
6+
"github.com/lightninglabs/taproot-assets/taprpc"
7+
"github.com/lightninglabs/taproot-assets/taprpc/mintrpc"
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
// testZeroValueAnchorSweep tests that zero-value anchor outputs (tombstones)
12+
// are automatically swept when creating new on-chain transactions.
13+
func testZeroValueAnchorSweep(t *harnessTest) {
14+
ctxb := context.Background()
15+
16+
// First, mint some simple assets.
17+
rpcAssets := MintAssetsConfirmBatch(
18+
t.t, t.lndHarness.Miner().Client, t.tapd,
19+
[]*mintrpc.MintAssetRequest{simpleAssets[0]},
20+
)
21+
22+
genInfo := rpcAssets[0].AssetGenesis
23+
assetAmount := simpleAssets[0].Asset.Amount
24+
25+
// Create a second tapd node.
26+
bobLnd := t.lndHarness.NewNodeWithCoins("Bob", nil)
27+
secondTapd := setupTapdHarness(t.t, t, bobLnd, t.universeServer)
28+
defer func() {
29+
require.NoError(t.t, secondTapd.stop(!*noDelete))
30+
}()
31+
32+
// Create an address for Bob to receive ALL assets (full value send).
33+
// This should create a tombstone output on Alice's side.
34+
bobAddr, err := secondTapd.NewAddr(ctxb, &taprpc.NewAddrRequest{
35+
AssetId: genInfo.AssetId,
36+
Amt: assetAmount, // Send ALL
37+
AssetVersion: rpcAssets[0].Version,
38+
})
39+
require.NoError(t.t, err)
40+
41+
// Send ALL assets to Bob, which should create a tombstone output.
42+
sendResp, _ := sendAssetsToAddr(t, t.tapd, bobAddr)
43+
44+
// Confirm the send and wait for completion.
45+
ConfirmAndAssertOutboundTransfer(
46+
t.t, t.lndHarness.Miner().Client, t.tapd, sendResp,
47+
genInfo.AssetId,
48+
[]uint64{0, assetAmount}, 0, 1,
49+
)
50+
AssertNonInteractiveRecvComplete(t.t, secondTapd, 1)
51+
52+
// At this point, Alice should have a tombstone UTXO.
53+
// Check Alice's UTXOs to see if there are any without assets (tombstones).
54+
aliceUtxos, err := t.tapd.ListUtxos(ctxb, &taprpc.ListUtxosRequest{})
55+
require.NoError(t.t, err)
56+
57+
tombstoneCount := 0
58+
for _, utxo := range aliceUtxos.ManagedUtxos {
59+
if len(utxo.Assets) == 0 {
60+
tombstoneCount++
61+
t.t.Logf("Found tombstone UTXO: %s, value=%d",
62+
utxo.OutPoint, utxo.AmtSat)
63+
}
64+
}
65+
66+
t.t.Logf("Alice has %d tombstone UTXOs before sweep", tombstoneCount)
67+
require.Greater(t.t, tombstoneCount, 0, "Should have at least one tombstone UTXO")
68+
69+
// Now mint more assets for Alice so she can create another transaction
70+
// that should sweep the tombstones.
71+
rpcAssets2 := MintAssetsConfirmBatch(
72+
t.t, t.lndHarness.Miner().Client, t.tapd,
73+
[]*mintrpc.MintAssetRequest{simpleAssets[1]},
74+
)
75+
76+
genInfo2 := rpcAssets2[0].AssetGenesis
77+
assetAmount2 := simpleAssets[1].Asset.Amount
78+
79+
// Create another address for Bob.
80+
bobAddr2, err := secondTapd.NewAddr(ctxb, &taprpc.NewAddrRequest{
81+
AssetId: genInfo2.AssetId,
82+
Amt: assetAmount2,
83+
AssetVersion: rpcAssets2[0].Version,
84+
})
85+
require.NoError(t.t, err)
86+
87+
// Send the new assets. This should sweep Alice's tombstone UTXOs.
88+
sendResp2, _ := sendAssetsToAddr(t, t.tapd, bobAddr2)
89+
90+
// Confirm the send.
91+
ConfirmAndAssertOutboundTransfer(
92+
t.t, t.lndHarness.Miner().Client, t.tapd, sendResp2,
93+
genInfo2.AssetId,
94+
[]uint64{0, assetAmount2}, 1, 2,
95+
)
96+
AssertNonInteractiveRecvComplete(t.t, secondTapd, 2)
97+
98+
// Check Alice's UTXOs again. The tombstones should have been swept.
99+
finalAliceUtxos, err := t.tapd.ListUtxos(ctxb, &taprpc.ListUtxosRequest{})
100+
require.NoError(t.t, err)
101+
102+
finalTombstoneCount := 0
103+
for _, utxo := range finalAliceUtxos.ManagedUtxos {
104+
if len(utxo.Assets) == 0 {
105+
finalTombstoneCount++
106+
t.t.Logf("Found tombstone UTXO after sweep: %s, value=%d",
107+
utxo.OutPoint, utxo.AmtSat)
108+
}
109+
}
110+
111+
t.t.Logf("Alice has %d tombstone UTXOs after sweep", finalTombstoneCount)
112+
113+
// We expect no tombstones after the sweep transaction.
114+
require.Equal(t.t, 0, finalTombstoneCount,
115+
"All tombstones should be swept")
116+
}

0 commit comments

Comments
 (0)