Skip to content

Commit 0a29e10

Browse files
committed
itest: separate tapd logs from itest
1 parent c2b0a37 commit 0a29e10

File tree

3 files changed

+147
-2
lines changed

3 files changed

+147
-2
lines changed

itest/tapd_harness.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ func newTapdHarness(t *testing.T, ht *harnessTest, cfg tapdConfig,
190190
}
191191

192192
tapCfg := tapcfg.DefaultConfig()
193-
tapCfg.LogDir = "."
193+
tapCfg.LogDir = *logDir
194194
tapCfg.MaxLogFiles = 99
195195
tapCfg.MaxLogFileSize = 999
196196

itest/test_harness.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"flag"
66
"fmt"
7+
"path/filepath"
78
"testing"
89
"time"
910

@@ -47,6 +48,10 @@ var (
4748
// integration test output.
4849
logLevel = flag.String("loglevel", "info", "Set the log level of the "+
4950
"integration test output")
51+
52+
// logDir is the directory for tapd and test logs.
53+
// We hardcode this to match the Makefile's -logdir=regtest flag.
54+
logDir = &[]string{"regtest"}[0]
5055
)
5156

5257
const (
@@ -201,12 +206,18 @@ func (h *harnessTest) shutdown(_ *testing.T) error {
201206
func (h *harnessTest) setupLogging() {
202207
h.logWriter = build.NewRotatingLogWriter()
203208

209+
// Initialize the log rotator with a file in the log directory.
204210
logConfig := build.DefaultLogConfig()
211+
// Disable console logging to avoid mixing with test output
212+
logConfig.Console.Disable = true
213+
logFile := filepath.Join(*logDir, "tapd.log")
214+
err := h.logWriter.InitLogRotator(logConfig.File, logFile)
215+
require.NoError(h.t, err)
216+
205217
h.logMgr = build.NewSubLoggerManager(
206218
build.NewDefaultLogHandlers(logConfig, h.logWriter)...,
207219
)
208220

209-
var err error
210221
h.interceptor, err = signal.Intercept()
211222
require.NoError(h.t, err)
212223

itest/zero_value_anchor_test.go

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
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+
t.t.Logf("UTXO %s has %d assets, value=%d", utxo.OutPoint, len(utxo.Assets), utxo.AmtSat)
60+
for _, asset := range utxo.Assets {
61+
t.t.Logf(" Asset %x: amount=%d", asset.AssetGenesis.AssetId, asset.Amount)
62+
}
63+
hasZeroAmountAsset := false
64+
for _, asset := range utxo.Assets {
65+
if asset.Amount == 0 {
66+
hasZeroAmountAsset = true
67+
break
68+
}
69+
}
70+
if hasZeroAmountAsset {
71+
tombstoneCount++
72+
t.t.Logf("Found tombstone UTXO: %s, value=%d",
73+
utxo.OutPoint, utxo.AmtSat)
74+
}
75+
}
76+
77+
t.t.Logf("Alice has %d tombstone UTXOs before sweep", tombstoneCount)
78+
require.Greater(t.t, tombstoneCount, 0, "Should have at least one tombstone UTXO")
79+
80+
// Now mint more assets for Alice so she can create another transaction
81+
// that should sweep the tombstones.
82+
rpcAssets2 := MintAssetsConfirmBatch(
83+
t.t, t.lndHarness.Miner().Client, t.tapd,
84+
[]*mintrpc.MintAssetRequest{simpleAssets[1]},
85+
)
86+
87+
genInfo2 := rpcAssets2[0].AssetGenesis
88+
assetAmount2 := simpleAssets[1].Asset.Amount
89+
90+
// Create another address for Bob.
91+
bobAddr2, err := secondTapd.NewAddr(ctxb, &taprpc.NewAddrRequest{
92+
AssetId: genInfo2.AssetId,
93+
Amt: assetAmount2,
94+
AssetVersion: rpcAssets2[0].Version,
95+
})
96+
require.NoError(t.t, err)
97+
98+
// Send the new assets. This should sweep Alice's tombstone UTXOs.
99+
sendResp2, _ := sendAssetsToAddr(t, t.tapd, bobAddr2)
100+
101+
// Confirm the send.
102+
ConfirmAndAssertOutboundTransfer(
103+
t.t, t.lndHarness.Miner().Client, t.tapd, sendResp2,
104+
genInfo2.AssetId,
105+
[]uint64{0, assetAmount2}, 1, 2,
106+
)
107+
AssertNonInteractiveRecvComplete(t.t, secondTapd, 2)
108+
109+
// Check Alice's UTXOs again. The tombstones should have been swept.
110+
finalAliceUtxos, err := t.tapd.ListUtxos(ctxb, &taprpc.ListUtxosRequest{})
111+
require.NoError(t.t, err)
112+
113+
finalTombstoneCount := 0
114+
for _, utxo := range finalAliceUtxos.ManagedUtxos {
115+
hasZeroAmountAsset := false
116+
for _, asset := range utxo.Assets {
117+
if asset.Amount == 0 {
118+
hasZeroAmountAsset = true
119+
break
120+
}
121+
}
122+
if hasZeroAmountAsset {
123+
finalTombstoneCount++
124+
t.t.Logf("Found tombstone UTXO after sweep: %s, value=%d",
125+
utxo.OutPoint, utxo.AmtSat)
126+
}
127+
}
128+
129+
t.t.Logf("Alice has %d tombstone UTXOs after sweep", finalTombstoneCount)
130+
131+
// We expect no tombstones after the sweep transaction.
132+
require.Equal(t.t, 0, finalTombstoneCount,
133+
"All tombstones should be swept")
134+
}

0 commit comments

Comments
 (0)