Skip to content

Commit a1ecc5c

Browse files
committed
itest: add test for consistent balance reporting
This commit adds an integration test to ensure consistent balance reporting across various scenarios. The test covers custom channel funding and list balance operations to verify that balance information is accurately reported between lnd's `ChannelBalance` and tapd's `ListBalance` RPCs, without accidental double reporting.
1 parent 0b45880 commit a1ecc5c

File tree

2 files changed

+202
-0
lines changed

2 files changed

+202
-0
lines changed

itest/litd_custom_channels_test.go

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"slices"
77
"time"
88

9+
"github.com/btcsuite/btcd/btcec/v2/schnorr"
910
"github.com/btcsuite/btcd/btcutil"
1011
"github.com/btcsuite/btcd/chaincfg/chainhash"
1112
"github.com/lightninglabs/taproot-assets/itest"
@@ -1894,3 +1895,200 @@ func testCustomChannelsLiquidityEdgeCases(_ context.Context,
18941895

18951896
logBalance(t.t, nodes, assetID, "after giant asset payment")
18961897
}
1898+
1899+
// testCustomChannelsBalanceConsistency is a test that test the balance .
1900+
func testCustomChannelsBalanceConsistency(_ context.Context,
1901+
net *NetworkHarness, t *harnessTest) {
1902+
1903+
ctxb := context.Background()
1904+
lndArgs := slices.Clone(lndArgsTemplate)
1905+
litdArgs := slices.Clone(litdArgsTemplate)
1906+
1907+
zane, err := net.NewNode(
1908+
t.t, "Zane", lndArgs, false, true, litdArgs...,
1909+
)
1910+
require.NoError(t.t, err)
1911+
1912+
litdArgs = append(litdArgs, fmt.Sprintf(
1913+
"--taproot-assets.proofcourieraddr=%s://%s",
1914+
proof.UniverseRpcCourierType, zane.Cfg.LitAddr(),
1915+
))
1916+
1917+
charlie, err := net.NewNode(
1918+
t.t, "Charlie", lndArgs, false, true, litdArgs...,
1919+
)
1920+
require.NoError(t.t, err)
1921+
dave, err := net.NewNode(t.t, "Dave", lndArgs, false, true, litdArgs...)
1922+
require.NoError(t.t, err)
1923+
1924+
nodes := []*HarnessNode{charlie, dave}
1925+
connectAllNodes(t.t, net, nodes)
1926+
fundAllNodes(t.t, net, nodes)
1927+
1928+
charlieTap := newTapClient(t.t, charlie)
1929+
daveTap := newTapClient(t.t, dave)
1930+
universeTap := newTapClient(t.t, zane)
1931+
1932+
// Mint an asset on Charlie and sync Dave to Charlie as the universe.
1933+
mintedAssets := itest.MintAssetsConfirmBatch(
1934+
t.t, t.lndHarness.Miner.Client, charlieTap,
1935+
[]*mintrpc.MintAssetRequest{
1936+
{
1937+
Asset: itestAsset,
1938+
},
1939+
},
1940+
)
1941+
cents := mintedAssets[0]
1942+
assetID := cents.AssetGenesis.AssetId
1943+
var groupKey []byte
1944+
if cents.AssetGroup != nil {
1945+
groupKey = cents.AssetGroup.TweakedGroupKey
1946+
}
1947+
1948+
t.Logf("Minted %d lightning cents, syncing universes...", cents.Amount)
1949+
syncUniverses(t.t, charlieTap, dave)
1950+
t.Logf("Universes synced between all nodes, distributing assets...")
1951+
1952+
charlieBalance := cents.Amount
1953+
1954+
// Charlie should have a single balance output with the full balance.
1955+
assertAssetBalance(t.t, charlieTap, assetID, cents.Amount)
1956+
1957+
// The script key should be local to charlie, and the script key should
1958+
// be known. It is after all the asset he just minted himself.
1959+
scriptKeyLocal := true
1960+
scriptKeyKnown := false
1961+
scriptKeyHasScriptPath := false
1962+
1963+
scriptKey, err := schnorr.ParsePubKey(cents.ScriptKey[1:])
1964+
require.NoError(t.t, err)
1965+
assertAssetExists(
1966+
t.t, charlieTap, assetID, charlieBalance,
1967+
scriptKey, scriptKeyLocal, scriptKeyKnown,
1968+
scriptKeyHasScriptPath,
1969+
)
1970+
1971+
fundingScriptTree := tapchannel.NewFundingScriptTree()
1972+
fundingScriptKey := fundingScriptTree.TaprootKey
1973+
fundingScriptTreeBytes := fundingScriptKey.SerializeCompressed()
1974+
1975+
fundRespCD, err := charlieTap.FundChannel(
1976+
ctxb, &tchrpc.FundChannelRequest{
1977+
AssetAmount: charlieBalance,
1978+
AssetId: assetID,
1979+
PeerPubkey: daveTap.node.PubKey[:],
1980+
FeeRateSatPerVbyte: 5,
1981+
PushSat: 0,
1982+
},
1983+
)
1984+
require.NoError(t.t, err)
1985+
t.Logf("Funded channel between Charlie and Dave: %v", fundRespCD)
1986+
1987+
// Make sure the pending channel shows up in the list and has the
1988+
// custom records set as JSON.
1989+
assertPendingChannels(
1990+
t.t, charlieTap.node, assetID, 1, charlieBalance, 0,
1991+
)
1992+
1993+
// Let's confirm the channel.
1994+
mineBlocks(t, net, 6, 1)
1995+
1996+
assertAssetBalance(t.t, charlieTap, assetID, cents.Amount)
1997+
1998+
// There should only be a single asset piece for Charlie, the one in the
1999+
// channel.
2000+
assertNumAssetOutputs(t.t, charlieTap, assetID, 1)
2001+
2002+
// The script key should now not be local anymore, since he funded a
2003+
// channel with it. Charlie does still know the script key though.
2004+
scriptKeyLocal = false
2005+
scriptKeyKnown = true
2006+
scriptKeyHasScriptPath = true
2007+
assertAssetExists(
2008+
t.t, charlieTap, assetID, charlieBalance,
2009+
fundingScriptKey, scriptKeyLocal, scriptKeyKnown,
2010+
scriptKeyHasScriptPath,
2011+
)
2012+
2013+
// Assert that the proofs for both channels has been uploaded to the
2014+
// designated Universe server.
2015+
assertUniverseProofExists(
2016+
t.t, universeTap, assetID, groupKey, fundingScriptTreeBytes,
2017+
fmt.Sprintf("%v:%v", fundRespCD.Txid, fundRespCD.OutputIndex),
2018+
)
2019+
2020+
// Make sure the channel shows the correct asset information.
2021+
assertAssetChan(
2022+
t.t, charlieTap.node, daveTap.node, charlieBalance, assetID,
2023+
)
2024+
2025+
logBalance(t.t, nodes, assetID, "initial")
2026+
2027+
// Normal case.
2028+
// Send 500 assets from Charlie to Dave.
2029+
sendAssetKeySendPayment(
2030+
t.t, charlie, dave, 500, assetID,
2031+
fn.None[int64](), lnrpc.Payment_SUCCEEDED,
2032+
fn.None[lnrpc.PaymentFailureReason](),
2033+
)
2034+
2035+
logBalance(t.t, nodes, assetID, "after 500 assets")
2036+
2037+
// Charlie should have a single balance output with the full balance.
2038+
// TODO: THIS ASSUMPTION SHOULD BE CHANGED AFTER TAPD STOPS INCLUDING
2039+
// NON-LOCAL BALANCES IN LISTBALANCES CALLS.
2040+
assertAssetBalance(t.t, charlieTap, assetID, charlieBalance)
2041+
assertAssetBalance(t.t, daveTap, assetID, 0)
2042+
2043+
// Send 10k sats from Charlie to Dave. Dave needs the sats to be able to
2044+
// send assets.
2045+
sendKeySendPayment(t.t, charlie, dave, 10000)
2046+
2047+
// Now Dave tries to send 250 assets.
2048+
sendAssetKeySendPayment(
2049+
t.t, dave, charlie, 250, assetID,
2050+
fn.None[int64](), lnrpc.Payment_SUCCEEDED,
2051+
fn.None[lnrpc.PaymentFailureReason](),
2052+
)
2053+
2054+
logBalance(t.t, nodes, assetID, "after 250 sats backwards")
2055+
2056+
// Charlie should have a single balance output with the full balance.
2057+
// TODO: THIS ASSUMPTION SHOULD BE CHANGED AFTER TAPD STOPS INCLUDING
2058+
// NON-LOCAL BALANCES IN LISTBALANCES CALLS.
2059+
assertAssetBalance(t.t, charlieTap, assetID, charlieBalance)
2060+
assertAssetBalance(t.t, daveTap, assetID, 0)
2061+
2062+
// We will now close the channel.
2063+
t.Logf("Close the channel between Charlie and Dave...")
2064+
charlieChanPoint := &lnrpc.ChannelPoint{
2065+
OutputIndex: uint32(fundRespCD.OutputIndex),
2066+
FundingTxid: &lnrpc.ChannelPoint_FundingTxidStr{
2067+
FundingTxidStr: fundRespCD.Txid,
2068+
},
2069+
}
2070+
2071+
closeChannelAndAssert(t, net, charlie, charlieChanPoint, false)
2072+
2073+
// Charlie should have a single balance output with the balance 250 less
2074+
// than the total amount minted.
2075+
assertAssetBalance(t.t, charlieTap, assetID, charlieBalance-250)
2076+
assertAssetBalance(t.t, daveTap, assetID, 250)
2077+
2078+
// The script key should now be local to both Charlie and Dave, since
2079+
// the channel was closed.
2080+
scriptKeyLocal = true
2081+
scriptKeyKnown = true
2082+
scriptKeyHasScriptPath = false
2083+
assertAssetExists(
2084+
t.t, charlieTap, assetID, charlieBalance-250,
2085+
nil, scriptKeyLocal, scriptKeyKnown, scriptKeyHasScriptPath,
2086+
)
2087+
assertAssetExists(
2088+
t.t, daveTap, assetID, 250,
2089+
nil, scriptKeyLocal, scriptKeyKnown, scriptKeyHasScriptPath,
2090+
)
2091+
2092+
assertNumAssetOutputs(t.t, charlieTap, assetID, 1)
2093+
assertNumAssetOutputs(t.t, daveTap, assetID, 1)
2094+
}

itest/litd_test_list_on_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,8 @@ var allTestCases = []*testCase{
4444
name: "test custom channels liquidity",
4545
test: testCustomChannelsLiquidityEdgeCases,
4646
},
47+
{
48+
name: "test custom channels balance consistency",
49+
test: testCustomChannelsBalanceConsistency,
50+
},
4751
}

0 commit comments

Comments
 (0)